From a4d1479cc50851b89dfdf80a4b458a095819efa5 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 1 Nov 2022 13:55:01 +0300 Subject: [PATCH 01/92] Add fann type and to_fann fun --- src/aeso_ast_to_fcode.erl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index c83d01a..89a1b47 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -58,6 +58,8 @@ | {contract_code, string()} %% for CREATE, by name | {typerep, ftype()}. +-type fann() :: [ {line, aeso_syntax:ann_line()} ]. + -type fexpr() :: {lit, flit()} | nil | {var, var_name()} @@ -374,6 +376,10 @@ to_fcode(Env, [{namespace, _, {con, _, Con}, Decls} | Code]) -> Env1 = decls_to_fcode(Env#{ context => {namespace, Con} }, Decls), to_fcode(Env1, Code). +-spec to_fann(aeso_syntax:ann()) -> fann(). +to_fann(Ann) -> + proplists:lookup_all(line, Ann). + -spec decls_to_fcode(env(), [aeso_syntax:decl()]) -> env(). decls_to_fcode(Env, Decls) -> %% First compute mapping from Sophia names to fun_names and add it to the -- 2.30.2 From 2118d82745709caf62ce15400a1d638be957e8e4 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 1 Nov 2022 16:47:09 +0300 Subject: [PATCH 02/92] Add fann() to funcall --- src/aeso_ast_to_fcode.erl | 56 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 89a1b47..dad0d15 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -72,7 +72,7 @@ | {set_proj, fexpr(), integer(), fexpr()} %% tuple, field, new_value | {op, op(), [fexpr()]} | {'let', var_name(), fexpr(), fexpr()} - | {funcall, fexpr(), [fexpr()]} %% Call to unknown function + | {funcall, fann(), fexpr(), [fexpr()]} %% Call to unknown function | {closure, fun_name(), fexpr()} | {switch, fsplit()} | {set_state, state_reg(), fexpr()} @@ -711,7 +711,7 @@ expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) -> end; %% Function calls -expr_to_fcode(Env, _, {app, _, Fun = {typed, _, FunE, {fun_t, _, NamedArgsT, ArgsT, Type}}, Args}) -> +expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, ArgsT, Type}}, Args}) -> Args1 = get_named_args(NamedArgsT, Args), FArgs = [expr_to_fcode(Env, Arg) || Arg <- Args1], case expr_to_fcode(Env, Fun) of @@ -739,7 +739,7 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, _, FunE, {fun_t, _, NamedArgsT, Arg FFun -> %% FFun is a closure, with first component the function name and %% second component the environment - Call = fun(X) -> {funcall, {proj, {var, X}, 0}, [{proj, {var, X}, 1} | FArgs]} end, + Call = fun(X) -> {funcall, to_fann(Ann), {proj, {var, X}, 0}, [{proj, {var, X}, 1} | FArgs]} end, case FFun of {var, X} -> Call(X); _ -> X = fresh_name(), @@ -1286,7 +1286,7 @@ lambda_lift_expr(Layout, Expr) -> {set_proj, A, I, B} -> {set_proj, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)}; {op, Op, As} -> {op, Op, lambda_lift_exprs(Layout, As)}; {'let', X, A, B} -> {'let', X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)}; - {funcall, A, Bs} -> {funcall, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)}; + {funcall, Ann, A, Bs} -> {funcall, Ann, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)}; {set_state, R, A} -> {set_state, R, lambda_lift_expr(Layout, A)}; {get_state, _} -> Expr; {switch, S} -> {switch, lambda_lift_expr(Layout, S)}; @@ -1370,7 +1370,7 @@ make_lets([E | Es], Xs, Body) -> inline_local_functions(Expr) -> bottom_up(fun inline_local_functions/2, Expr). -inline_local_functions(Env, {funcall, {proj, {var, Y}, 0}, [{proj, {var, Y}, 1} | Args]} = Expr) -> +inline_local_functions(Env, {funcall, _, {proj, {var, Y}, 0}, [{proj, {var, Y}, 1} | Args]} = Expr) -> %% TODO: Don't always inline local funs? case maps:get(Y, Env, free) of {lam, Xs, Body} -> let_bind(lists:zip(Xs, Args), Body); @@ -1609,7 +1609,7 @@ read_only({split, _, _, Cases}) -> read_only(Cases); read_only({nosplit, E}) -> read_only(E); read_only({'case', _, Split}) -> read_only(Split); read_only({'let', _, A, B}) -> read_only([A, B]); -read_only({funcall, _, _}) -> false; +read_only({funcall, _, _, _}) -> false; read_only({closure, _, _}) -> internal_error(no_closures_here); read_only(Es) when is_list(Es) -> lists:all(fun read_only/1, Es). @@ -1837,7 +1837,7 @@ free_vars(Expr) -> {set_proj, A, _, B} -> free_vars([A, B]); {op, _, As} -> free_vars(As); {'let', X, A, B} -> free_vars([A, {lam, [X], B}]); - {funcall, A, Bs} -> free_vars([A | Bs]); + {funcall, _, A, Bs} -> free_vars([A | Bs]); {set_state, _, A} -> free_vars(A); {get_state, _} -> []; {lam, Xs, B} -> free_vars(B) -- lists:sort(Xs); @@ -1868,7 +1868,7 @@ used_defs(Expr) -> {set_proj, A, _, B} -> used_defs([A, B]); {op, _, As} -> used_defs(As); {'let', _, A, B} -> used_defs([A, B]); - {funcall, A, Bs} -> used_defs([A | Bs]); + {funcall, _, A, Bs} -> used_defs([A | Bs]); {set_state, _, A} -> used_defs(A); {get_state, _} -> []; {lam, _, B} -> used_defs(B); @@ -1898,7 +1898,7 @@ bottom_up(F, Env, Expr) -> {proj, E, I} -> {proj, bottom_up(F, Env, E), I}; {set_proj, R, I, E} -> {set_proj, bottom_up(F, Env, R), I, bottom_up(F, Env, E)}; {op, Op, Es} -> {op, Op, [bottom_up(F, Env, E) || E <- Es]}; - {funcall, Fun, Es} -> {funcall, bottom_up(F, Env, Fun), [bottom_up(F, Env, E) || E <- Es]}; + {funcall, Ann, Fun, Es} -> {funcall, Ann, bottom_up(F, Env, Fun), [bottom_up(F, Env, E) || E <- Es]}; {set_state, R, E} -> {set_state, R, bottom_up(F, Env, E)}; {get_state, _} -> Expr; {closure, F, CEnv} -> {closure, F, bottom_up(F, Env, CEnv)}; @@ -1941,26 +1941,26 @@ get_named_arg({named_arg_t, _, {id, _, Name}, _, Default}, Args) -> -spec rename([{var_name(), var_name()}], fexpr()) -> fexpr(). rename(Ren, Expr) -> case Expr of - {lit, _} -> Expr; - nil -> nil; - {var, X} -> {var, rename_var(Ren, X)}; - {def, D, Es} -> {def, D, [rename(Ren, E) || E <- Es]}; - {def_u, _, _} -> Expr; - {builtin, B, Es} -> {builtin, B, [rename(Ren, E) || E <- Es]}; - {builtin_u, _, _} -> Expr; - {builtin_u, _, _, _} -> Expr; + {lit, _} -> Expr; + nil -> nil; + {var, X} -> {var, rename_var(Ren, X)}; + {def, D, Es} -> {def, D, [rename(Ren, E) || E <- Es]}; + {def_u, _, _} -> Expr; + {builtin, B, Es} -> {builtin, B, [rename(Ren, E) || E <- Es]}; + {builtin_u, _, _} -> Expr; + {builtin_u, _, _, _} -> Expr; {remote, ArgsT, RetT, Ct, F, Es} -> {remote, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; {remote_u, ArgsT, RetT, Ct, F} -> {remote_u, ArgsT, RetT, rename(Ren, Ct), F}; - {con, Ar, I, Es} -> {con, Ar, I, [rename(Ren, E) || E <- Es]}; - {tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]}; - {proj, E, I} -> {proj, rename(Ren, E), I}; - {set_proj, R, I, E} -> {set_proj, rename(Ren, R), I, rename(Ren, E)}; - {op, Op, Es} -> {op, Op, [rename(Ren, E) || E <- Es]}; - {funcall, Fun, Es} -> {funcall, rename(Ren, Fun), [rename(Ren, E) || E <- Es]}; - {set_state, R, E} -> {set_state, R, rename(Ren, E)}; - {get_state, _} -> Expr; - {closure, F, Env} -> {closure, F, rename(Ren, Env)}; - {switch, Split} -> {switch, rename_split(Ren, Split)}; + {con, Ar, I, Es} -> {con, Ar, I, [rename(Ren, E) || E <- Es]}; + {tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]}; + {proj, E, I} -> {proj, rename(Ren, E), I}; + {set_proj, R, I, E} -> {set_proj, rename(Ren, R), I, rename(Ren, E)}; + {op, Op, Es} -> {op, Op, [rename(Ren, E) || E <- Es]}; + {funcall, Ann, Fun, Es} -> {funcall, Ann, rename(Ren, Fun), [rename(Ren, E) || E <- Es]}; + {set_state, R, E} -> {set_state, R, rename(Ren, E)}; + {get_state, _} -> Expr; + {closure, F, Env} -> {closure, F, rename(Ren, Env)}; + {switch, Split} -> {switch, rename_split(Ren, Split)}; {lam, Xs, B} -> {Zs, Ren1} = rename_bindings(Ren, Xs), {lam, Zs, rename(Ren1, B)}; @@ -2202,7 +2202,7 @@ pp_fexpr({remote_u, ArgsT, RetT, Ct, Fun}) -> pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun), pp_text(" : "), pp_ftype({function, ArgsT, RetT})]); pp_fexpr({remote, ArgsT, RetT, Ct, Fun, As}) -> pp_call(pp_parens(pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun), pp_text(" : "), pp_ftype({function, ArgsT, RetT})])), As); -pp_fexpr({funcall, Fun, As}) -> +pp_fexpr({funcall, _, Fun, As}) -> pp_call(pp_fexpr(Fun), As); pp_fexpr({set_state, R, A}) -> pp_call(pp_text("set_state"), [{lit, {int, R}}, A]); -- 2.30.2 From dc5a119bc6a4ad79ac8104308a419d14ea25143b Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 1 Nov 2022 17:05:53 +0300 Subject: [PATCH 03/92] Add fann() to closure --- src/aeso_ast_to_fcode.erl | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index dad0d15..3142b62 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -73,7 +73,7 @@ | {op, op(), [fexpr()]} | {'let', var_name(), fexpr(), fexpr()} | {funcall, fann(), fexpr(), [fexpr()]} %% Call to unknown function - | {closure, fun_name(), fexpr()} + | {closure, fann(), fun_name(), fexpr()} | {switch, fsplit()} | {set_state, state_reg(), fexpr()} | {get_state, state_reg()} @@ -380,6 +380,9 @@ to_fcode(Env, [{namespace, _, {con, _, Con}, Decls} | Code]) -> to_fann(Ann) -> proplists:lookup_all(line, Ann). +-spec get_fann(fexpr()) -> fann(). +get_fann(FExpr) -> element(2, FExpr). + -spec decls_to_fcode(env(), [aeso_syntax:decl()]) -> env(). decls_to_fcode(Env, Decls) -> %% First compute mapping from Sophia names to fun_names and add it to the @@ -1246,7 +1249,7 @@ lifted_fun(FVs, Xs, Body) -> make_closure(FVs, Xs, Body) -> Fun = add_lambda_fun(lifted_fun(FVs, Xs, Body)), Tup = fun([Y]) -> Y; (Ys) -> {tuple, Ys} end, - {closure, Fun, Tup([{var, Y} || Y <- FVs])}. + {closure, get_fann(Body), Fun, Tup([{var, Y} || Y <- FVs])}. lambda_lift_expr(Layout, {lam, Xs, Body}) -> FVs = free_vars({lam, Xs, Body}), @@ -1276,7 +1279,7 @@ lambda_lift_expr(Layout, Expr) -> {lit, _} -> Expr; nil -> Expr; {var, _} -> Expr; - {closure, _, _} -> Expr; + {closure, _, _, _} -> Expr; {def, D, As} -> {def, D, lambda_lift_exprs(Layout, As)}; {builtin, B, As} -> {builtin, B, lambda_lift_exprs(Layout, As)}; {remote, ArgsT, RetT, Ct, F, As} -> {remote, ArgsT, RetT, lambda_lift_expr(Layout, Ct), F, lambda_lift_exprs(Layout, As)}; @@ -1610,7 +1613,7 @@ read_only({nosplit, E}) -> read_only(E); read_only({'case', _, Split}) -> read_only(Split); read_only({'let', _, A, B}) -> read_only([A, B]); read_only({funcall, _, _, _}) -> false; -read_only({closure, _, _}) -> internal_error(no_closures_here); +read_only({closure, _, _, _}) -> internal_error(no_closures_here); read_only(Es) when is_list(Es) -> lists:all(fun read_only/1, Es). %% --- Deadcode elimination --- @@ -1841,7 +1844,7 @@ free_vars(Expr) -> {set_state, _, A} -> free_vars(A); {get_state, _} -> []; {lam, Xs, B} -> free_vars(B) -- lists:sort(Xs); - {closure, _, A} -> free_vars(A); + {closure, _, _, A} -> free_vars(A); {switch, A} -> free_vars(A); {split, _, X, As} -> free_vars([{var, X} | As]); {nosplit, A} -> free_vars(A); @@ -1872,7 +1875,7 @@ used_defs(Expr) -> {set_state, _, A} -> used_defs(A); {get_state, _} -> []; {lam, _, B} -> used_defs(B); - {closure, F, A} -> lists:umerge([F], used_defs(A)); + {closure, _, F, A} -> lists:umerge([F], used_defs(A)); {switch, A} -> used_defs(A); {split, _, _, As} -> used_defs(As); {nosplit, A} -> used_defs(A); @@ -1901,7 +1904,7 @@ bottom_up(F, Env, Expr) -> {funcall, Ann, Fun, Es} -> {funcall, Ann, bottom_up(F, Env, Fun), [bottom_up(F, Env, E) || E <- Es]}; {set_state, R, E} -> {set_state, R, bottom_up(F, Env, E)}; {get_state, _} -> Expr; - {closure, F, CEnv} -> {closure, F, bottom_up(F, Env, CEnv)}; + {closure, Ann, F, CEnv} -> {closure, Ann, F, bottom_up(F, Env, CEnv)}; {switch, Split} -> {switch, bottom_up(F, Env, Split)}; {lam, Xs, B} -> {lam, Xs, bottom_up(F, Env, B)}; {'let', X, E, Body} -> @@ -1959,7 +1962,7 @@ rename(Ren, Expr) -> {funcall, Ann, Fun, Es} -> {funcall, Ann, rename(Ren, Fun), [rename(Ren, E) || E <- Es]}; {set_state, R, E} -> {set_state, R, rename(Ren, E)}; {get_state, _} -> Expr; - {closure, F, Env} -> {closure, F, rename(Ren, Env)}; + {closure, Ann, F, Env} -> {closure, Ann, F, rename(Ren, Env)}; {switch, Split} -> {switch, rename_split(Ren, Split)}; {lam, Xs, B} -> {Zs, Ren1} = rename_bindings(Ren, Xs), @@ -2160,7 +2163,7 @@ pp_fexpr({proj, E, I}) -> pp_fexpr({lam, Xs, A}) -> pp_par([pp_fexpr({tuple, [{var, X} || X <- Xs]}), pp_text("=>"), prettypr:nest(2, pp_fexpr(A))]); -pp_fexpr({closure, Fun, ClEnv}) -> +pp_fexpr({closure, _, Fun, ClEnv}) -> FVs = case ClEnv of {tuple, Xs} -> Xs; {var, _} -> [ClEnv] -- 2.30.2 From 1043473696c0e0c2b8ea86b56807a1c03917369e Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 1 Nov 2022 17:19:17 +0300 Subject: [PATCH 04/92] Add fann() to set_state --- src/aeso_ast_to_fcode.erl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 3142b62..25cf72c 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -75,7 +75,7 @@ | {funcall, fann(), fexpr(), [fexpr()]} %% Call to unknown function | {closure, fann(), fun_name(), fexpr()} | {switch, fsplit()} - | {set_state, state_reg(), fexpr()} + | {set_state, fann(), state_reg(), fexpr()} | {get_state, state_reg()} %% The following (unapplied top-level functions/builtins and %% lambdas) are generated by the fcode compiler, but translated @@ -1115,7 +1115,7 @@ op_builtins() -> ]. set_state({reg, R}, Val) -> - {set_state, R, Val}; + {set_state, get_fann(Val), R, Val}; set_state({tuple, Ls}, Val) -> ?make_let(X, Val, lists:foldr(fun({I, L}, Code) -> @@ -1290,7 +1290,7 @@ lambda_lift_expr(Layout, Expr) -> {op, Op, As} -> {op, Op, lambda_lift_exprs(Layout, As)}; {'let', X, A, B} -> {'let', X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)}; {funcall, Ann, A, Bs} -> {funcall, Ann, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)}; - {set_state, R, A} -> {set_state, R, lambda_lift_expr(Layout, A)}; + {set_state, Ann, R, A} -> {set_state, Ann, R, lambda_lift_expr(Layout, A)}; {get_state, _} -> Expr; {switch, S} -> {switch, lambda_lift_expr(Layout, S)}; {split, Type, X, Alts} -> {split, Type, X, lambda_lift_exprs(Layout, Alts)}; @@ -1598,7 +1598,7 @@ read_only({proj, E, _}) -> read_only(E); read_only({set_proj, A, _, B}) -> read_only([A, B]); read_only({op, _, Es}) -> read_only(Es); read_only({get_state, _}) -> true; -read_only({set_state, _, _}) -> false; +read_only({set_state, _, _, _}) -> false; read_only({def_u, _, _}) -> true; read_only({remote_u, _, _, _, _}) -> true; read_only({builtin_u, _, _}) -> true; @@ -1841,7 +1841,7 @@ free_vars(Expr) -> {op, _, As} -> free_vars(As); {'let', X, A, B} -> free_vars([A, {lam, [X], B}]); {funcall, _, A, Bs} -> free_vars([A | Bs]); - {set_state, _, A} -> free_vars(A); + {set_state, _, _, A} -> free_vars(A); {get_state, _} -> []; {lam, Xs, B} -> free_vars(B) -- lists:sort(Xs); {closure, _, _, A} -> free_vars(A); @@ -1872,7 +1872,7 @@ used_defs(Expr) -> {op, _, As} -> used_defs(As); {'let', _, A, B} -> used_defs([A, B]); {funcall, _, A, Bs} -> used_defs([A | Bs]); - {set_state, _, A} -> used_defs(A); + {set_state, _, _, A} -> used_defs(A); {get_state, _} -> []; {lam, _, B} -> used_defs(B); {closure, _, F, A} -> lists:umerge([F], used_defs(A)); @@ -1902,7 +1902,7 @@ bottom_up(F, Env, Expr) -> {set_proj, R, I, E} -> {set_proj, bottom_up(F, Env, R), I, bottom_up(F, Env, E)}; {op, Op, Es} -> {op, Op, [bottom_up(F, Env, E) || E <- Es]}; {funcall, Ann, Fun, Es} -> {funcall, Ann, bottom_up(F, Env, Fun), [bottom_up(F, Env, E) || E <- Es]}; - {set_state, R, E} -> {set_state, R, bottom_up(F, Env, E)}; + {set_state, Ann, R, E} -> {set_state, Ann, R, bottom_up(F, Env, E)}; {get_state, _} -> Expr; {closure, Ann, F, CEnv} -> {closure, Ann, F, bottom_up(F, Env, CEnv)}; {switch, Split} -> {switch, bottom_up(F, Env, Split)}; @@ -1960,7 +1960,7 @@ rename(Ren, Expr) -> {set_proj, R, I, E} -> {set_proj, rename(Ren, R), I, rename(Ren, E)}; {op, Op, Es} -> {op, Op, [rename(Ren, E) || E <- Es]}; {funcall, Ann, Fun, Es} -> {funcall, Ann, rename(Ren, Fun), [rename(Ren, E) || E <- Es]}; - {set_state, R, E} -> {set_state, R, rename(Ren, E)}; + {set_state, Ann, R, E} -> {set_state, Ann, R, rename(Ren, E)}; {get_state, _} -> Expr; {closure, Ann, F, Env} -> {closure, Ann, F, rename(Ren, Env)}; {switch, Split} -> {switch, rename_split(Ren, Split)}; @@ -2207,7 +2207,7 @@ pp_fexpr({remote, ArgsT, RetT, Ct, Fun, As}) -> pp_call(pp_parens(pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun), pp_text(" : "), pp_ftype({function, ArgsT, RetT})])), As); pp_fexpr({funcall, _, Fun, As}) -> pp_call(pp_fexpr(Fun), As); -pp_fexpr({set_state, R, A}) -> +pp_fexpr({set_state, _, R, A}) -> pp_call(pp_text("set_state"), [{lit, {int, R}}, A]); pp_fexpr({get_state, R}) -> pp_call(pp_text("get_state"), [{lit, {int, R}}]); -- 2.30.2 From dd57fd9abe9331a73c56d93da94d95fe83a26a9c Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 1 Nov 2022 18:07:12 +0300 Subject: [PATCH 05/92] Add fann() to remote_u --- src/aeso_ast_to_fcode.erl | 80 +++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 25cf72c..569a0b8 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -81,7 +81,7 @@ %% lambdas) are generated by the fcode compiler, but translated %% to closures by the lambda lifter. | {def_u, fun_name(), arity()} - | {remote_u, [ftype()], ftype(), fexpr(), fun_name()} + | {remote_u, fann(), [ftype()], ftype(), fexpr(), fun_name()} | {builtin_u, builtin(), arity()} | {builtin_u, builtin(), arity(), [fexpr()]} %% Typerep arguments to be added after normal args. | {lam, [var_name()], fexpr()}. @@ -595,14 +595,14 @@ expr_to_fcode(Env, _Type, {tuple, _, Es}) -> make_tuple([expr_to_fcode(Env, E) || E <- Es]); %% Records -expr_to_fcode(Env, Type, {proj, _Ann, Rec = {typed, _, _, RecType}, {id, _, X}}) -> +expr_to_fcode(Env, Type, {proj, Ann, Rec = {typed, _, _, RecType}, {id, _, X}}) -> case RecType of {con, _, _} when X == "address" -> {op, contract_to_address, [expr_to_fcode(Env, Rec)]}; {con, _, _} -> {fun_t, _, _, Args, Ret} = Type, FArgs = [type_to_fcode(Env, Arg) || Arg <- Args], - {remote_u, FArgs, type_to_fcode(Env, Ret), expr_to_fcode(Env, Rec), + {remote_u, to_fann(Ann), FArgs, type_to_fcode(Env, Ret), expr_to_fcode(Env, Rec), {entrypoint, list_to_binary(X)}}; {record_t, [_]} -> expr_to_fcode(Env, Rec); %% Singleton record {record_t, _} -> @@ -738,7 +738,7 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A end; {builtin_u, B, _Ar} -> builtin_to_fcode(state_layout(Env), B, FArgs); {def_u, F, _Ar} -> {def, F, FArgs}; - {remote_u, RArgsT, RRetT, Ct, RFun} -> {remote, RArgsT, RRetT, Ct, RFun, FArgs}; + {remote_u, Ann, RArgsT, RRetT, Ct, RFun} -> {remote, RArgsT, RRetT, Ct, RFun, FArgs}; FFun -> %% FFun is a closure, with first component the function name and %% second component the environment @@ -1267,7 +1267,7 @@ lambda_lift_expr(Layout, UExpr) when element(1, UExpr) == def_u; element(1, UExp def_u -> {def, F, Args} end, make_closure([], Xs, Body); -lambda_lift_expr(Layout, {remote_u, ArgsT, RetT, Ct, F}) -> +lambda_lift_expr(Layout, {remote_u, _, ArgsT, RetT, Ct, F}) -> FVs = free_vars(Ct), Ct1 = lambda_lift_expr(Layout, Ct), NamedArgCount = 3, @@ -1589,32 +1589,32 @@ safe_to_duplicate({tuple, []}) -> true; safe_to_duplicate(_) -> false. -spec read_only(fexpr() | fsplit() | fcase() | [fexpr()] | [fcase()]) -> boolean(). -read_only({lit, _}) -> true; -read_only({var, _}) -> true; -read_only(nil) -> true; -read_only({con, _, _, Es}) -> read_only(Es); -read_only({tuple, Es}) -> read_only(Es); -read_only({proj, E, _}) -> read_only(E); -read_only({set_proj, A, _, B}) -> read_only([A, B]); -read_only({op, _, Es}) -> read_only(Es); -read_only({get_state, _}) -> true; -read_only({set_state, _, _, _}) -> false; -read_only({def_u, _, _}) -> true; -read_only({remote_u, _, _, _, _}) -> true; -read_only({builtin_u, _, _}) -> true; -read_only({builtin_u, _, _, _}) -> true; -read_only({lam, _, _}) -> true; -read_only({def, _, _}) -> false; %% TODO: purity analysis -read_only({remote, _, _, _, _, _}) -> false; -read_only({builtin, _, _}) -> false; %% TODO: some builtins are -read_only({switch, Split}) -> read_only(Split); -read_only({split, _, _, Cases}) -> read_only(Cases); -read_only({nosplit, E}) -> read_only(E); -read_only({'case', _, Split}) -> read_only(Split); -read_only({'let', _, A, B}) -> read_only([A, B]); -read_only({funcall, _, _, _}) -> false; -read_only({closure, _, _, _}) -> internal_error(no_closures_here); -read_only(Es) when is_list(Es) -> lists:all(fun read_only/1, Es). +read_only({lit, _}) -> true; +read_only({var, _}) -> true; +read_only(nil) -> true; +read_only({con, _, _, Es}) -> read_only(Es); +read_only({tuple, Es}) -> read_only(Es); +read_only({proj, E, _}) -> read_only(E); +read_only({set_proj, A, _, B}) -> read_only([A, B]); +read_only({op, _, Es}) -> read_only(Es); +read_only({get_state, _}) -> true; +read_only({set_state, _, _, _}) -> false; +read_only({def_u, _, _}) -> true; +read_only({remote_u, _, _, _, _, _}) -> true; +read_only({builtin_u, _, _}) -> true; +read_only({builtin_u, _, _, _}) -> true; +read_only({lam, _, _}) -> true; +read_only({def, _, _}) -> false; %% TODO: purity analysis +read_only({remote, _, _, _, _, _}) -> false; +read_only({builtin, _, _}) -> false; %% TODO: some builtins are +read_only({switch, Split}) -> read_only(Split); +read_only({split, _, _, Cases}) -> read_only(Cases); +read_only({nosplit, E}) -> read_only(E); +read_only({'case', _, Split}) -> read_only(Split); +read_only({'let', _, A, B}) -> read_only([A, B]); +read_only({funcall, _, _, _}) -> false; +read_only({closure, _, _, _}) -> internal_error(no_closures_here); +read_only(Es) when is_list(Es) -> lists:all(fun read_only/1, Es). %% --- Deadcode elimination --- @@ -1829,8 +1829,8 @@ free_vars(Expr) -> nil -> []; {def, _, As} -> free_vars(As); {def_u, _, _} -> []; - {remote, _, _, Ct, _, As} -> free_vars([Ct | As]); - {remote_u, _, _, Ct, _} -> free_vars(Ct); + {remote, _, _, Ct, _, As} -> free_vars([Ct | As]); + {remote_u, _, _, _, Ct, _} -> free_vars(Ct); {builtin, _, As} -> free_vars(As); {builtin_u, _, _} -> []; {builtin_u, _, _, _} -> []; %% Typereps are always literals @@ -1860,8 +1860,8 @@ used_defs(Expr) -> nil -> []; {def, F, As} -> lists:umerge([F], used_defs(As)); {def_u, F, _} -> [F]; - {remote, _, _, Ct, _, As} -> used_defs([Ct | As]); - {remote_u, _, _, Ct, _} -> used_defs(Ct); + {remote, _, _, Ct, _, As} -> used_defs([Ct | As]); + {remote_u, _, _, _, Ct, _} -> used_defs(Ct); {builtin, _, As} -> used_defs(As); {builtin_u, _, _} -> []; {builtin_u, _, _, _} -> []; @@ -1894,8 +1894,8 @@ bottom_up(F, Env, Expr) -> {builtin, B, Es} -> {builtin, B, [bottom_up(F, Env, E) || E <- Es]}; {builtin_u, _, _} -> Expr; {builtin_u, _, _, _} -> Expr; - {remote, ArgsT, RetT, Ct, Fun, Es} -> {remote, ArgsT, RetT, bottom_up(F, Env, Ct), Fun, [bottom_up(F, Env, E) || E <- Es]}; - {remote_u, ArgsT, RetT, Ct, Fun} -> {remote_u, ArgsT, RetT, bottom_up(F, Env, Ct), Fun}; + {remote, ArgsT, RetT, Ct, Fun, Es} -> {remote, ArgsT, RetT, bottom_up(F, Env, Ct), Fun, [bottom_up(F, Env, E) || E <- Es]}; + {remote_u, Ann, ArgsT, RetT, Ct, Fun} -> {remote_u, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun}; {con, Ar, I, Es} -> {con, Ar, I, [bottom_up(F, Env, E) || E <- Es]}; {tuple, Es} -> {tuple, [bottom_up(F, Env, E) || E <- Es]}; {proj, E, I} -> {proj, bottom_up(F, Env, E), I}; @@ -1952,8 +1952,8 @@ rename(Ren, Expr) -> {builtin, B, Es} -> {builtin, B, [rename(Ren, E) || E <- Es]}; {builtin_u, _, _} -> Expr; {builtin_u, _, _, _} -> Expr; - {remote, ArgsT, RetT, Ct, F, Es} -> {remote, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; - {remote_u, ArgsT, RetT, Ct, F} -> {remote_u, ArgsT, RetT, rename(Ren, Ct), F}; + {remote, ArgsT, RetT, Ct, F, Es} -> {remote, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; + {remote_u, Ann, ArgsT, RetT, Ct, F} -> {remote_u, Ann, ArgsT, RetT, rename(Ren, Ct), F}; {con, Ar, I, Es} -> {con, Ar, I, [rename(Ren, E) || E <- Es]}; {tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]}; {proj, E, I} -> {proj, rename(Ren, E), I}; @@ -2201,7 +2201,7 @@ pp_fexpr({builtin_u, B, N, TypeArgs}) -> pp_beside([pp_text(B), pp_text("@"), pp_fexpr({tuple, TypeArgs}), pp_text("/"), pp_text(N)]); pp_fexpr({builtin, B, As}) -> pp_call(pp_text(B), As); -pp_fexpr({remote_u, ArgsT, RetT, Ct, Fun}) -> +pp_fexpr({remote_u, _, ArgsT, RetT, Ct, Fun}) -> pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun), pp_text(" : "), pp_ftype({function, ArgsT, RetT})]); pp_fexpr({remote, ArgsT, RetT, Ct, Fun, As}) -> pp_call(pp_parens(pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun), pp_text(" : "), pp_ftype({function, ArgsT, RetT})])), As); -- 2.30.2 From b35441c40e602a21d5dc90f16195dbeffd6625c9 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 1 Nov 2022 18:23:25 +0300 Subject: [PATCH 06/92] Add fann() to remote --- src/aeso_ast_to_fcode.erl | 80 +++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 569a0b8..16bbdb6 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -64,7 +64,7 @@ | nil | {var, var_name()} | {def, fun_name(), [fexpr()]} - | {remote, [ftype()], ftype(), fexpr(), fun_name(), [fexpr()]} + | {remote, fann(), [ftype()], ftype(), fexpr(), fun_name(), [fexpr()]} | {builtin, builtin(), [fexpr()]} | {con, arities(), tag(), [fexpr()]} | {tuple, [fexpr()]} @@ -738,7 +738,7 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A end; {builtin_u, B, _Ar} -> builtin_to_fcode(state_layout(Env), B, FArgs); {def_u, F, _Ar} -> {def, F, FArgs}; - {remote_u, Ann, RArgsT, RRetT, Ct, RFun} -> {remote, RArgsT, RRetT, Ct, RFun, FArgs}; + {remote_u, Ann, RArgsT, RRetT, Ct, RFun} -> {remote, Ann, RArgsT, RRetT, Ct, RFun, FArgs}; FFun -> %% FFun is a closure, with first component the function name and %% second component the environment @@ -1267,13 +1267,13 @@ lambda_lift_expr(Layout, UExpr) when element(1, UExpr) == def_u; element(1, UExp def_u -> {def, F, Args} end, make_closure([], Xs, Body); -lambda_lift_expr(Layout, {remote_u, _, ArgsT, RetT, Ct, F}) -> +lambda_lift_expr(Layout, {remote_u, Ann, ArgsT, RetT, Ct, F}) -> FVs = free_vars(Ct), Ct1 = lambda_lift_expr(Layout, Ct), NamedArgCount = 3, Xs = [ lists:concat(["arg", I]) || I <- lists:seq(1, length(ArgsT) + NamedArgCount) ], Args = [{var, X} || X <- Xs], - make_closure(FVs, Xs, {remote, ArgsT, RetT, Ct1, F, Args}); + make_closure(FVs, Xs, {remote, Ann, ArgsT, RetT, Ct1, F, Args}); lambda_lift_expr(Layout, Expr) -> case Expr of {lit, _} -> Expr; @@ -1282,7 +1282,7 @@ lambda_lift_expr(Layout, Expr) -> {closure, _, _, _} -> Expr; {def, D, As} -> {def, D, lambda_lift_exprs(Layout, As)}; {builtin, B, As} -> {builtin, B, lambda_lift_exprs(Layout, As)}; - {remote, ArgsT, RetT, Ct, F, As} -> {remote, ArgsT, RetT, lambda_lift_expr(Layout, Ct), F, lambda_lift_exprs(Layout, As)}; + {remote, Ann, ArgsT, RetT, Ct, F, As} -> {remote, Ann, ArgsT, RetT, lambda_lift_expr(Layout, Ct), F, lambda_lift_exprs(Layout, As)}; {con, Ar, C, As} -> {con, Ar, C, lambda_lift_exprs(Layout, As)}; {tuple, As} -> {tuple, lambda_lift_exprs(Layout, As)}; {proj, A, I} -> {proj, lambda_lift_expr(Layout, A), I}; @@ -1589,32 +1589,32 @@ safe_to_duplicate({tuple, []}) -> true; safe_to_duplicate(_) -> false. -spec read_only(fexpr() | fsplit() | fcase() | [fexpr()] | [fcase()]) -> boolean(). -read_only({lit, _}) -> true; -read_only({var, _}) -> true; -read_only(nil) -> true; -read_only({con, _, _, Es}) -> read_only(Es); -read_only({tuple, Es}) -> read_only(Es); -read_only({proj, E, _}) -> read_only(E); -read_only({set_proj, A, _, B}) -> read_only([A, B]); -read_only({op, _, Es}) -> read_only(Es); -read_only({get_state, _}) -> true; -read_only({set_state, _, _, _}) -> false; -read_only({def_u, _, _}) -> true; -read_only({remote_u, _, _, _, _, _}) -> true; -read_only({builtin_u, _, _}) -> true; -read_only({builtin_u, _, _, _}) -> true; -read_only({lam, _, _}) -> true; -read_only({def, _, _}) -> false; %% TODO: purity analysis -read_only({remote, _, _, _, _, _}) -> false; -read_only({builtin, _, _}) -> false; %% TODO: some builtins are -read_only({switch, Split}) -> read_only(Split); -read_only({split, _, _, Cases}) -> read_only(Cases); -read_only({nosplit, E}) -> read_only(E); -read_only({'case', _, Split}) -> read_only(Split); -read_only({'let', _, A, B}) -> read_only([A, B]); -read_only({funcall, _, _, _}) -> false; -read_only({closure, _, _, _}) -> internal_error(no_closures_here); -read_only(Es) when is_list(Es) -> lists:all(fun read_only/1, Es). +read_only({lit, _}) -> true; +read_only({var, _}) -> true; +read_only(nil) -> true; +read_only({con, _, _, Es}) -> read_only(Es); +read_only({tuple, Es}) -> read_only(Es); +read_only({proj, E, _}) -> read_only(E); +read_only({set_proj, A, _, B}) -> read_only([A, B]); +read_only({op, _, Es}) -> read_only(Es); +read_only({get_state, _}) -> true; +read_only({set_state, _, _, _}) -> false; +read_only({def_u, _, _}) -> true; +read_only({remote_u, _, _, _, _, _}) -> true; +read_only({builtin_u, _, _}) -> true; +read_only({builtin_u, _, _, _}) -> true; +read_only({lam, _, _}) -> true; +read_only({def, _, _}) -> false; %% TODO: purity analysis +read_only({remote, _, _, _, _, _, _}) -> false; +read_only({builtin, _, _}) -> false; %% TODO: some builtins are +read_only({switch, Split}) -> read_only(Split); +read_only({split, _, _, Cases}) -> read_only(Cases); +read_only({nosplit, E}) -> read_only(E); +read_only({'case', _, Split}) -> read_only(Split); +read_only({'let', _, A, B}) -> read_only([A, B]); +read_only({funcall, _, _, _}) -> false; +read_only({closure, _, _, _}) -> internal_error(no_closures_here); +read_only(Es) when is_list(Es) -> lists:all(fun read_only/1, Es). %% --- Deadcode elimination --- @@ -1829,8 +1829,8 @@ free_vars(Expr) -> nil -> []; {def, _, As} -> free_vars(As); {def_u, _, _} -> []; - {remote, _, _, Ct, _, As} -> free_vars([Ct | As]); - {remote_u, _, _, _, Ct, _} -> free_vars(Ct); + {remote, _, _, _, Ct, _, As} -> free_vars([Ct | As]); + {remote_u, _, _, _, Ct, _} -> free_vars(Ct); {builtin, _, As} -> free_vars(As); {builtin_u, _, _} -> []; {builtin_u, _, _, _} -> []; %% Typereps are always literals @@ -1860,8 +1860,8 @@ used_defs(Expr) -> nil -> []; {def, F, As} -> lists:umerge([F], used_defs(As)); {def_u, F, _} -> [F]; - {remote, _, _, Ct, _, As} -> used_defs([Ct | As]); - {remote_u, _, _, _, Ct, _} -> used_defs(Ct); + {remote, _, _, _, Ct, _, As} -> used_defs([Ct | As]); + {remote_u, _, _, _, Ct, _} -> used_defs(Ct); {builtin, _, As} -> used_defs(As); {builtin_u, _, _} -> []; {builtin_u, _, _, _} -> []; @@ -1894,8 +1894,8 @@ bottom_up(F, Env, Expr) -> {builtin, B, Es} -> {builtin, B, [bottom_up(F, Env, E) || E <- Es]}; {builtin_u, _, _} -> Expr; {builtin_u, _, _, _} -> Expr; - {remote, ArgsT, RetT, Ct, Fun, Es} -> {remote, ArgsT, RetT, bottom_up(F, Env, Ct), Fun, [bottom_up(F, Env, E) || E <- Es]}; - {remote_u, Ann, ArgsT, RetT, Ct, Fun} -> {remote_u, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun}; + {remote, Ann, ArgsT, RetT, Ct, Fun, Es} -> {remote, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun, [bottom_up(F, Env, E) || E <- Es]}; + {remote_u, Ann, ArgsT, RetT, Ct, Fun} -> {remote_u, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun}; {con, Ar, I, Es} -> {con, Ar, I, [bottom_up(F, Env, E) || E <- Es]}; {tuple, Es} -> {tuple, [bottom_up(F, Env, E) || E <- Es]}; {proj, E, I} -> {proj, bottom_up(F, Env, E), I}; @@ -1952,8 +1952,8 @@ rename(Ren, Expr) -> {builtin, B, Es} -> {builtin, B, [rename(Ren, E) || E <- Es]}; {builtin_u, _, _} -> Expr; {builtin_u, _, _, _} -> Expr; - {remote, ArgsT, RetT, Ct, F, Es} -> {remote, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; - {remote_u, Ann, ArgsT, RetT, Ct, F} -> {remote_u, Ann, ArgsT, RetT, rename(Ren, Ct), F}; + {remote, Ann, ArgsT, RetT, Ct, F, Es} -> {remote, Ann, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; + {remote_u, Ann, ArgsT, RetT, Ct, F} -> {remote_u, Ann, ArgsT, RetT, rename(Ren, Ct), F}; {con, Ar, I, Es} -> {con, Ar, I, [rename(Ren, E) || E <- Es]}; {tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]}; {proj, E, I} -> {proj, rename(Ren, E), I}; @@ -2203,7 +2203,7 @@ pp_fexpr({builtin, B, As}) -> pp_call(pp_text(B), As); pp_fexpr({remote_u, _, ArgsT, RetT, Ct, Fun}) -> pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun), pp_text(" : "), pp_ftype({function, ArgsT, RetT})]); -pp_fexpr({remote, ArgsT, RetT, Ct, Fun, As}) -> +pp_fexpr({remote, _, ArgsT, RetT, Ct, Fun, As}) -> pp_call(pp_parens(pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun), pp_text(" : "), pp_ftype({function, ArgsT, RetT})])), As); pp_fexpr({funcall, _, Fun, As}) -> pp_call(pp_fexpr(Fun), As); -- 2.30.2 From 404bb3386308f34f6b461e8f74c90c714cfa9e8c Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 2 Nov 2022 12:10:44 +0300 Subject: [PATCH 07/92] Add fann() to proj --- src/aeso_ast_to_fcode.erl | 43 ++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 16bbdb6..4bda78c 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -68,7 +68,7 @@ | {builtin, builtin(), [fexpr()]} | {con, arities(), tag(), [fexpr()]} | {tuple, [fexpr()]} - | {proj, fexpr(), integer()} + | {proj, fann(), fexpr(), integer()} | {set_proj, fexpr(), integer(), fexpr()} %% tuple, field, new_value | {op, op(), [fexpr()]} | {'let', var_name(), fexpr(), fexpr()} @@ -606,7 +606,7 @@ expr_to_fcode(Env, Type, {proj, Ann, Rec = {typed, _, _, RecType}, {id, _, X}}) {entrypoint, list_to_binary(X)}}; {record_t, [_]} -> expr_to_fcode(Env, Rec); %% Singleton record {record_t, _} -> - {proj, expr_to_fcode(Env, Rec), field_index(Rec, X)} + {proj, to_fann(Ann), expr_to_fcode(Env, Rec), field_index(Rec, X)} end; expr_to_fcode(Env, {record_t, [FieldT]}, {record, _Ann, [_] = Fields}) -> @@ -626,9 +626,9 @@ expr_to_fcode(Env, {record_t, [FieldT]}, {record, _Ann, Rec, Fields}) -> {set, E} -> expr_to_fcode(Env, E); {upd, Z, E} -> {'let', Z, expr_to_fcode(Env, Rec), expr_to_fcode(bind_var(Env, Z), E)} end; -expr_to_fcode(Env, {record_t, FieldTypes}, {record, _Ann, Rec, Fields}) -> +expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) -> X = fresh_name(), - Proj = fun(I) -> {proj, {var, X}, I - 1} end, + Proj = fun(I) -> {proj, to_fann(Ann), {var, X}, I - 1} end, Comp = fun({I, false}) -> Proj(I); ({_, {set, E}}) -> expr_to_fcode(Env, E); ({I, {upd, Z, E}}) -> {'let', Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)} @@ -742,7 +742,8 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A FFun -> %% FFun is a closure, with first component the function name and %% second component the environment - Call = fun(X) -> {funcall, to_fann(Ann), {proj, {var, X}, 0}, [{proj, {var, X}, 1} | FArgs]} end, + FAnn = to_fann(Ann), + Call = fun(X) -> {funcall, FAnn, {proj, FAnn, {var, X}, 0}, [{proj, FAnn, {var, X}, 1} | FArgs]} end, case FFun of {var, X} -> Call(X); _ -> X = fresh_name(), @@ -1119,7 +1120,7 @@ set_state({reg, R}, Val) -> set_state({tuple, Ls}, Val) -> ?make_let(X, Val, lists:foldr(fun({I, L}, Code) -> - {'let', "_", set_state(L, {proj, X, I - 1}), Code} + {'let', "_", set_state(L, {proj, get_fann(Val), X, I - 1}), Code} end, {tuple, []}, indexed(Ls))). get_state({reg, R}) -> @@ -1239,7 +1240,7 @@ lifted_fun([Z], Xs, Body) -> body => Body }; lifted_fun(FVs, Xs, Body) -> Z = "%env", - Proj = fun({I, Y}, E) -> {'let', Y, {proj, {var, Z}, I - 1}, E} end, + Proj = fun({I, Y}, E) -> {'let', Y, {proj, get_fann(Body), {var, Z}, I - 1}, E} end, #{ attrs => [private], args => [{Z, any} | [{X, any} || X <- Xs]], return => any, @@ -1285,7 +1286,7 @@ lambda_lift_expr(Layout, Expr) -> {remote, Ann, ArgsT, RetT, Ct, F, As} -> {remote, Ann, ArgsT, RetT, lambda_lift_expr(Layout, Ct), F, lambda_lift_exprs(Layout, As)}; {con, Ar, C, As} -> {con, Ar, C, lambda_lift_exprs(Layout, As)}; {tuple, As} -> {tuple, lambda_lift_exprs(Layout, As)}; - {proj, A, I} -> {proj, lambda_lift_expr(Layout, A), I}; + {proj, Ann, A, I} -> {proj, Ann, lambda_lift_expr(Layout, A), I}; {set_proj, A, I, B} -> {set_proj, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)}; {op, Op, As} -> {op, Op, lambda_lift_exprs(Layout, As)}; {'let', X, A, B} -> {'let', X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)}; @@ -1373,7 +1374,7 @@ make_lets([E | Es], Xs, Body) -> inline_local_functions(Expr) -> bottom_up(fun inline_local_functions/2, Expr). -inline_local_functions(Env, {funcall, _, {proj, {var, Y}, 0}, [{proj, {var, Y}, 1} | Args]} = Expr) -> +inline_local_functions(Env, {funcall, _, {proj, _, {var, Y}, 0}, [{proj, _, {var, Y}, 1} | Args]} = Expr) -> %% TODO: Don't always inline local funs? case maps:get(Y, Env, free) of {lam, Xs, Body} -> let_bind(lists:zip(Xs, Args), Body); @@ -1387,8 +1388,8 @@ let_floating(Expr) -> bottom_up(fun let_float/2, Expr). let_float(_, {'let', X, E, Body}) -> pull_out_let({'let', X, {here, E}, Body}); -let_float(_, {proj, E, I}) -> - pull_out_let({proj, {here, E}, I}); +let_float(_, {proj, Ann, E, I}) -> + pull_out_let({proj, Ann, {here, E}, I}); let_float(_, {set_proj, E, I, V}) -> pull_out_let({set_proj, {here, E}, I, {here, V}}); let_float(_, {op, Op, Es}) -> @@ -1433,7 +1434,7 @@ simplifier(Expr) -> %% (e₀, .., en).i -> %% let _ = e₀ in .. let x = ei in .. let _ = en in x -simplify(_Env, {proj, {tuple, Es}, I}) -> +simplify(_Env, {proj, _, {tuple, Es}, I}) -> It = lists:nth(I + 1, Es), X = fresh_name(), Dup = safe_to_duplicate(It), @@ -1452,7 +1453,7 @@ simplify(_Env, {proj, {tuple, Es}, I}) -> end, Val, indexed(Es)); %% let x = e in .. x.i .. -simplify(Env, {proj, {var, X}, I} = Expr) -> +simplify(Env, {proj, _, {var, X}, I} = Expr) -> case simpl_proj(Env, I, {var, X}) of false -> Expr; E -> E @@ -1479,7 +1480,7 @@ simpl_proj(Env, I, Expr) -> {tuple, Es} -> IfSafe(lists:nth(I + 1, Es)); {set_proj, _, I, Val} -> IfSafe(Val); {set_proj, E, _, _} -> simpl_proj(Env, I, E); - {proj, E, J} -> simpl_proj(Env, I, simpl_proj(Env, J, E)); + {proj, _, E, J} -> simpl_proj(Env, I, simpl_proj(Env, J, E)); _ -> false end. @@ -1555,7 +1556,7 @@ constructor_form(Env, Expr) -> {tuple, Es} -> {tuple, setnth(I + 1, V, Es)}; _ -> false end; - {proj, E, I} -> + {proj, _, E, I} -> case constructor_form(Env, E) of {tuple, Es} -> constructor_form(Env, lists:nth(I + 1, Es)); _ -> false @@ -1594,7 +1595,7 @@ read_only({var, _}) -> true; read_only(nil) -> true; read_only({con, _, _, Es}) -> read_only(Es); read_only({tuple, Es}) -> read_only(Es); -read_only({proj, E, _}) -> read_only(E); +read_only({proj, _, E, _}) -> read_only(E); read_only({set_proj, A, _, B}) -> read_only([A, B]); read_only({op, _, Es}) -> read_only(Es); read_only({get_state, _}) -> true; @@ -1836,7 +1837,7 @@ free_vars(Expr) -> {builtin_u, _, _, _} -> []; %% Typereps are always literals {con, _, _, As} -> free_vars(As); {tuple, As} -> free_vars(As); - {proj, A, _} -> free_vars(A); + {proj, _, A, _} -> free_vars(A); {set_proj, A, _, B} -> free_vars([A, B]); {op, _, As} -> free_vars(As); {'let', X, A, B} -> free_vars([A, {lam, [X], B}]); @@ -1867,7 +1868,7 @@ used_defs(Expr) -> {builtin_u, _, _, _} -> []; {con, _, _, As} -> used_defs(As); {tuple, As} -> used_defs(As); - {proj, A, _} -> used_defs(A); + {proj, _, A, _} -> used_defs(A); {set_proj, A, _, B} -> used_defs([A, B]); {op, _, As} -> used_defs(As); {'let', _, A, B} -> used_defs([A, B]); @@ -1898,7 +1899,7 @@ bottom_up(F, Env, Expr) -> {remote_u, Ann, ArgsT, RetT, Ct, Fun} -> {remote_u, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun}; {con, Ar, I, Es} -> {con, Ar, I, [bottom_up(F, Env, E) || E <- Es]}; {tuple, Es} -> {tuple, [bottom_up(F, Env, E) || E <- Es]}; - {proj, E, I} -> {proj, bottom_up(F, Env, E), I}; + {proj, Ann, E, I} -> {proj, Ann, bottom_up(F, Env, E), I}; {set_proj, R, I, E} -> {set_proj, bottom_up(F, Env, R), I, bottom_up(F, Env, E)}; {op, Op, Es} -> {op, Op, [bottom_up(F, Env, E) || E <- Es]}; {funcall, Ann, Fun, Es} -> {funcall, Ann, bottom_up(F, Env, Fun), [bottom_up(F, Env, E) || E <- Es]}; @@ -1956,7 +1957,7 @@ rename(Ren, Expr) -> {remote_u, Ann, ArgsT, RetT, Ct, F} -> {remote_u, Ann, ArgsT, RetT, rename(Ren, Ct), F}; {con, Ar, I, Es} -> {con, Ar, I, [rename(Ren, E) || E <- Es]}; {tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]}; - {proj, E, I} -> {proj, rename(Ren, E), I}; + {proj, Ann, E, I} -> {proj, Ann, rename(Ren, E), I}; {set_proj, R, I, E} -> {set_proj, rename(Ren, R), I, rename(Ren, E)}; {op, Op, Es} -> {op, Op, [rename(Ren, E) || E <- Es]}; {funcall, Ann, Fun, Es} -> {funcall, Ann, rename(Ren, Fun), [rename(Ren, E) || E <- Es]}; @@ -2158,7 +2159,7 @@ pp_fexpr({con, _, I, Es}) -> pp_fexpr({tuple, Es})); pp_fexpr({tuple, Es}) -> pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_fexpr(E) || E <- Es]))); -pp_fexpr({proj, E, I}) -> +pp_fexpr({proj, _, E, I}) -> pp_beside([pp_fexpr(E), pp_text("."), pp_int(I)]); pp_fexpr({lam, Xs, A}) -> pp_par([pp_fexpr({tuple, [{var, X} || X <- Xs]}), pp_text("=>"), -- 2.30.2 From 74f0b3a2dba4b9ef35bf538ea41cd8a30b3aa5a0 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 2 Nov 2022 12:15:37 +0300 Subject: [PATCH 08/92] Add fann() to set_proj --- src/aeso_ast_to_fcode.erl | 202 +++++++++++++++++++------------------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 4bda78c..56e198c 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -69,7 +69,7 @@ | {con, arities(), tag(), [fexpr()]} | {tuple, [fexpr()]} | {proj, fann(), fexpr(), integer()} - | {set_proj, fexpr(), integer(), fexpr()} %% tuple, field, new_value + | {set_proj, fann(), fexpr(), integer(), fexpr()} %% tuple, field, new_value | {op, op(), [fexpr()]} | {'let', var_name(), fexpr(), fexpr()} | {funcall, fann(), fexpr(), [fexpr()]} %% Call to unknown function @@ -634,8 +634,8 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) -> ({I, {upd, Z, E}}) -> {'let', Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)} end, Set = fun({_, false}, R) -> R; - ({I, {set, E}}, R) -> {set_proj, R, I - 1, expr_to_fcode(Env, E)}; - ({I, {upd, Z, E}}, R) -> {set_proj, R, I - 1, + ({I, {set, E}}, R) -> {set_proj, to_fann(Ann), R, I - 1, expr_to_fcode(Env, E)}; + ({I, {upd, Z, E}}, R) -> {set_proj, to_fann(Ann), R, I - 1, {'let', Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)}} end, Expand = length(Fields) == length(FieldTypes), @@ -1277,26 +1277,26 @@ lambda_lift_expr(Layout, {remote_u, Ann, ArgsT, RetT, Ct, F}) -> make_closure(FVs, Xs, {remote, Ann, ArgsT, RetT, Ct1, F, Args}); lambda_lift_expr(Layout, Expr) -> case Expr of - {lit, _} -> Expr; - nil -> Expr; - {var, _} -> Expr; - {closure, _, _, _} -> Expr; - {def, D, As} -> {def, D, lambda_lift_exprs(Layout, As)}; - {builtin, B, As} -> {builtin, B, lambda_lift_exprs(Layout, As)}; + {lit, _} -> Expr; + nil -> Expr; + {var, _} -> Expr; + {closure, _, _, _} -> Expr; + {def, D, As} -> {def, D, lambda_lift_exprs(Layout, As)}; + {builtin, B, As} -> {builtin, B, lambda_lift_exprs(Layout, As)}; {remote, Ann, ArgsT, RetT, Ct, F, As} -> {remote, Ann, ArgsT, RetT, lambda_lift_expr(Layout, Ct), F, lambda_lift_exprs(Layout, As)}; - {con, Ar, C, As} -> {con, Ar, C, lambda_lift_exprs(Layout, As)}; - {tuple, As} -> {tuple, lambda_lift_exprs(Layout, As)}; - {proj, Ann, A, I} -> {proj, Ann, lambda_lift_expr(Layout, A), I}; - {set_proj, A, I, B} -> {set_proj, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)}; - {op, Op, As} -> {op, Op, lambda_lift_exprs(Layout, As)}; - {'let', X, A, B} -> {'let', X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)}; - {funcall, Ann, A, Bs} -> {funcall, Ann, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)}; - {set_state, Ann, R, A} -> {set_state, Ann, R, lambda_lift_expr(Layout, A)}; - {get_state, _} -> Expr; - {switch, S} -> {switch, lambda_lift_expr(Layout, S)}; - {split, Type, X, Alts} -> {split, Type, X, lambda_lift_exprs(Layout, Alts)}; - {nosplit, A} -> {nosplit, lambda_lift_expr(Layout, A)}; - {'case', P, S} -> {'case', P, lambda_lift_expr(Layout, S)} + {con, Ar, C, As} -> {con, Ar, C, lambda_lift_exprs(Layout, As)}; + {tuple, As} -> {tuple, lambda_lift_exprs(Layout, As)}; + {proj, Ann, A, I} -> {proj, Ann, lambda_lift_expr(Layout, A), I}; + {set_proj, Ann, A, I, B} -> {set_proj, Ann, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)}; + {op, Op, As} -> {op, Op, lambda_lift_exprs(Layout, As)}; + {'let', X, A, B} -> {'let', X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)}; + {funcall, Ann, A, Bs} -> {funcall, Ann, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)}; + {set_state, Ann, R, A} -> {set_state, Ann, R, lambda_lift_expr(Layout, A)}; + {get_state, _} -> Expr; + {switch, S} -> {switch, lambda_lift_expr(Layout, S)}; + {split, Type, X, Alts} -> {split, Type, X, lambda_lift_exprs(Layout, Alts)}; + {nosplit, A} -> {nosplit, lambda_lift_expr(Layout, A)}; + {'case', P, S} -> {'case', P, lambda_lift_expr(Layout, S)} end. lambda_lift_exprs(Layout, As) -> [lambda_lift_expr(Layout, A) || A <- As]. @@ -1355,8 +1355,8 @@ bind_subexpressions(Expr) -> bind_subexpressions(_, {tuple, Es}) -> ?make_lets(Xs, Es, {tuple, Xs}); -bind_subexpressions(_, {set_proj, A, I, B}) -> - ?make_lets([X, Y], [A, B], {set_proj, X, I, Y}); +bind_subexpressions(_, {set_proj, Ann, A, I, B}) -> + ?make_lets([X, Y], [A, B], {set_proj, Ann, X, I, Y}); bind_subexpressions(_, E) -> E. make_lets(Es, Body) -> make_lets(Es, [], Body). @@ -1390,8 +1390,8 @@ let_float(_, {'let', X, E, Body}) -> pull_out_let({'let', X, {here, E}, Body}); let_float(_, {proj, Ann, E, I}) -> pull_out_let({proj, Ann, {here, E}, I}); -let_float(_, {set_proj, E, I, V}) -> - pull_out_let({set_proj, {here, E}, I, {here, V}}); +let_float(_, {set_proj, Ann, E, I, V}) -> + pull_out_let({set_proj, Ann, {here, E}, I, {here, V}}); let_float(_, {op, Op, Es}) -> {Lets, Es1} = pull_out_let([{here, E} || E <- Es]), let_bind(Lets, {op, Op, Es1}); @@ -1475,13 +1475,13 @@ simpl_proj(Env, I, Expr) -> false -> false end end, case Expr of - false -> false; - {var, X} -> simpl_proj(Env, I, maps:get(X, Env, false)); - {tuple, Es} -> IfSafe(lists:nth(I + 1, Es)); - {set_proj, _, I, Val} -> IfSafe(Val); - {set_proj, E, _, _} -> simpl_proj(Env, I, E); - {proj, _, E, J} -> simpl_proj(Env, I, simpl_proj(Env, J, E)); - _ -> false + false -> false; + {var, X} -> simpl_proj(Env, I, maps:get(X, Env, false)); + {tuple, Es} -> IfSafe(lists:nth(I + 1, Es)); + {set_proj, _, _, I, Val} -> IfSafe(Val); + {set_proj, _, E, _, _} -> simpl_proj(Env, I, E); + {proj, _, E, J} -> simpl_proj(Env, I, simpl_proj(Env, J, E)); + _ -> false end. get_catchalls(Alts) -> @@ -1551,7 +1551,7 @@ constructor_form(Env, Expr) -> free -> false; E -> constructor_form(Env, E) %% TODO: shadowing? end; - {set_proj, E, I, V} -> + {set_proj, _, E, I, V} -> case constructor_form(Env, E) of {tuple, Es} -> {tuple, setnth(I + 1, V, Es)}; _ -> false @@ -1596,7 +1596,7 @@ read_only(nil) -> true; read_only({con, _, _, Es}) -> read_only(Es); read_only({tuple, Es}) -> read_only(Es); read_only({proj, _, E, _}) -> read_only(E); -read_only({set_proj, A, _, B}) -> read_only([A, B]); +read_only({set_proj, _, A, _, B}) -> read_only([A, B]); read_only({op, _, Es}) -> read_only(Es); read_only({get_state, _}) -> true; read_only({set_state, _, _, _}) -> false; @@ -1825,62 +1825,62 @@ free_vars(Xs) when is_list(Xs) -> lists:umerge([ free_vars(X) || X <- Xs ]); free_vars(Expr) -> case Expr of - {var, X} -> [X]; - {lit, _} -> []; - nil -> []; - {def, _, As} -> free_vars(As); - {def_u, _, _} -> []; + {var, X} -> [X]; + {lit, _} -> []; + nil -> []; + {def, _, As} -> free_vars(As); + {def_u, _, _} -> []; {remote, _, _, _, Ct, _, As} -> free_vars([Ct | As]); {remote_u, _, _, _, Ct, _} -> free_vars(Ct); - {builtin, _, As} -> free_vars(As); - {builtin_u, _, _} -> []; - {builtin_u, _, _, _} -> []; %% Typereps are always literals - {con, _, _, As} -> free_vars(As); - {tuple, As} -> free_vars(As); - {proj, _, A, _} -> free_vars(A); - {set_proj, A, _, B} -> free_vars([A, B]); - {op, _, As} -> free_vars(As); - {'let', X, A, B} -> free_vars([A, {lam, [X], B}]); - {funcall, _, A, Bs} -> free_vars([A | Bs]); - {set_state, _, _, A} -> free_vars(A); - {get_state, _} -> []; - {lam, Xs, B} -> free_vars(B) -- lists:sort(Xs); - {closure, _, _, A} -> free_vars(A); - {switch, A} -> free_vars(A); - {split, _, X, As} -> free_vars([{var, X} | As]); - {nosplit, A} -> free_vars(A); - {'case', P, A} -> free_vars(A) -- lists:sort(fsplit_pat_vars(P)) + {builtin, _, As} -> free_vars(As); + {builtin_u, _, _} -> []; + {builtin_u, _, _, _} -> []; %% Typereps are always literals + {con, _, _, As} -> free_vars(As); + {tuple, As} -> free_vars(As); + {proj, _, A, _} -> free_vars(A); + {set_proj, _, A, _, B} -> free_vars([A, B]); + {op, _, As} -> free_vars(As); + {'let', X, A, B} -> free_vars([A, {lam, [X], B}]); + {funcall, _, A, Bs} -> free_vars([A | Bs]); + {set_state, _, _, A} -> free_vars(A); + {get_state, _} -> []; + {lam, Xs, B} -> free_vars(B) -- lists:sort(Xs); + {closure, _, _, A} -> free_vars(A); + {switch, A} -> free_vars(A); + {split, _, X, As} -> free_vars([{var, X} | As]); + {nosplit, A} -> free_vars(A); + {'case', P, A} -> free_vars(A) -- lists:sort(fsplit_pat_vars(P)) end. used_defs(Xs) when is_list(Xs) -> lists:umerge([ used_defs(X) || X <- Xs ]); used_defs(Expr) -> case Expr of - {var, _} -> []; - {lit, _} -> []; - nil -> []; - {def, F, As} -> lists:umerge([F], used_defs(As)); - {def_u, F, _} -> [F]; + {var, _} -> []; + {lit, _} -> []; + nil -> []; + {def, F, As} -> lists:umerge([F], used_defs(As)); + {def_u, F, _} -> [F]; {remote, _, _, _, Ct, _, As} -> used_defs([Ct | As]); {remote_u, _, _, _, Ct, _} -> used_defs(Ct); - {builtin, _, As} -> used_defs(As); - {builtin_u, _, _} -> []; - {builtin_u, _, _, _} -> []; - {con, _, _, As} -> used_defs(As); - {tuple, As} -> used_defs(As); - {proj, _, A, _} -> used_defs(A); - {set_proj, A, _, B} -> used_defs([A, B]); - {op, _, As} -> used_defs(As); - {'let', _, A, B} -> used_defs([A, B]); - {funcall, _, A, Bs} -> used_defs([A | Bs]); - {set_state, _, _, A} -> used_defs(A); - {get_state, _} -> []; - {lam, _, B} -> used_defs(B); - {closure, _, F, A} -> lists:umerge([F], used_defs(A)); - {switch, A} -> used_defs(A); - {split, _, _, As} -> used_defs(As); - {nosplit, A} -> used_defs(A); - {'case', _, A} -> used_defs(A) + {builtin, _, As} -> used_defs(As); + {builtin_u, _, _} -> []; + {builtin_u, _, _, _} -> []; + {con, _, _, As} -> used_defs(As); + {tuple, As} -> used_defs(As); + {proj, _, A, _} -> used_defs(A); + {set_proj, _, A, _, B} -> used_defs([A, B]); + {op, _, As} -> used_defs(As); + {'let', _, A, B} -> used_defs([A, B]); + {funcall, _, A, Bs} -> used_defs([A | Bs]); + {set_state, _, _, A} -> used_defs(A); + {get_state, _} -> []; + {lam, _, B} -> used_defs(B); + {closure, _, F, A} -> lists:umerge([F], used_defs(A)); + {switch, A} -> used_defs(A); + {split, _, _, As} -> used_defs(As); + {nosplit, A} -> used_defs(A); + {'case', _, A} -> used_defs(A) end. bottom_up(F, Expr) -> bottom_up(F, #{}, Expr). @@ -1900,7 +1900,7 @@ bottom_up(F, Env, Expr) -> {con, Ar, I, Es} -> {con, Ar, I, [bottom_up(F, Env, E) || E <- Es]}; {tuple, Es} -> {tuple, [bottom_up(F, Env, E) || E <- Es]}; {proj, Ann, E, I} -> {proj, Ann, bottom_up(F, Env, E), I}; - {set_proj, R, I, E} -> {set_proj, bottom_up(F, Env, R), I, bottom_up(F, Env, E)}; + {set_proj, Ann, R, I, E} -> {set_proj, Ann, bottom_up(F, Env, R), I, bottom_up(F, Env, E)}; {op, Op, Es} -> {op, Op, [bottom_up(F, Env, E) || E <- Es]}; {funcall, Ann, Fun, Es} -> {funcall, Ann, bottom_up(F, Env, Fun), [bottom_up(F, Env, E) || E <- Es]}; {set_state, Ann, R, E} -> {set_state, Ann, R, bottom_up(F, Env, E)}; @@ -1945,26 +1945,26 @@ get_named_arg({named_arg_t, _, {id, _, Name}, _, Default}, Args) -> -spec rename([{var_name(), var_name()}], fexpr()) -> fexpr(). rename(Ren, Expr) -> case Expr of - {lit, _} -> Expr; - nil -> nil; - {var, X} -> {var, rename_var(Ren, X)}; - {def, D, Es} -> {def, D, [rename(Ren, E) || E <- Es]}; - {def_u, _, _} -> Expr; - {builtin, B, Es} -> {builtin, B, [rename(Ren, E) || E <- Es]}; - {builtin_u, _, _} -> Expr; - {builtin_u, _, _, _} -> Expr; + {lit, _} -> Expr; + nil -> nil; + {var, X} -> {var, rename_var(Ren, X)}; + {def, D, Es} -> {def, D, [rename(Ren, E) || E <- Es]}; + {def_u, _, _} -> Expr; + {builtin, B, Es} -> {builtin, B, [rename(Ren, E) || E <- Es]}; + {builtin_u, _, _} -> Expr; + {builtin_u, _, _, _} -> Expr; {remote, Ann, ArgsT, RetT, Ct, F, Es} -> {remote, Ann, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; {remote_u, Ann, ArgsT, RetT, Ct, F} -> {remote_u, Ann, ArgsT, RetT, rename(Ren, Ct), F}; - {con, Ar, I, Es} -> {con, Ar, I, [rename(Ren, E) || E <- Es]}; - {tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]}; - {proj, Ann, E, I} -> {proj, Ann, rename(Ren, E), I}; - {set_proj, R, I, E} -> {set_proj, rename(Ren, R), I, rename(Ren, E)}; - {op, Op, Es} -> {op, Op, [rename(Ren, E) || E <- Es]}; - {funcall, Ann, Fun, Es} -> {funcall, Ann, rename(Ren, Fun), [rename(Ren, E) || E <- Es]}; - {set_state, Ann, R, E} -> {set_state, Ann, R, rename(Ren, E)}; - {get_state, _} -> Expr; - {closure, Ann, F, Env} -> {closure, Ann, F, rename(Ren, Env)}; - {switch, Split} -> {switch, rename_split(Ren, Split)}; + {con, Ar, I, Es} -> {con, Ar, I, [rename(Ren, E) || E <- Es]}; + {tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]}; + {proj, Ann, E, I} -> {proj, Ann, rename(Ren, E), I}; + {set_proj, Ann, R, I, E} -> {set_proj, Ann, rename(Ren, R), I, rename(Ren, E)}; + {op, Op, Es} -> {op, Op, [rename(Ren, E) || E <- Es]}; + {funcall, Ann, Fun, Es} -> {funcall, Ann, rename(Ren, Fun), [rename(Ren, E) || E <- Es]}; + {set_state, Ann, R, E} -> {set_state, Ann, R, rename(Ren, E)}; + {get_state, _} -> Expr; + {closure, Ann, F, Env} -> {closure, Ann, F, rename(Ren, Env)}; + {switch, Split} -> {switch, rename_split(Ren, Split)}; {lam, Xs, B} -> {Zs, Ren1} = rename_bindings(Ren, Xs), {lam, Zs, rename(Ren1, B)}; @@ -2170,7 +2170,7 @@ pp_fexpr({closure, _, Fun, ClEnv}) -> {var, _} -> [ClEnv] end, pp_call(pp_text("__CLOSURE__"), [{def, Fun} | FVs]); -pp_fexpr({set_proj, E, I, A}) -> +pp_fexpr({set_proj, _, E, I, A}) -> pp_beside(pp_fexpr(E), pp_braces(pp_beside([pp_int(I), pp_text(" = "), pp_fexpr(A)]))); pp_fexpr({op, Op, [A, B] = Args}) -> case is_infix(Op) of -- 2.30.2 From 44ec5db132b7e8516c229fb07c911ea3dd935293 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 4 Nov 2022 20:47:40 +0300 Subject: [PATCH 09/92] Add fann() to def and def_u --- src/aeso_ast_to_fcode.erl | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 56e198c..5514155 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -63,7 +63,7 @@ -type fexpr() :: {lit, flit()} | nil | {var, var_name()} - | {def, fun_name(), [fexpr()]} + | {def, fann(), fun_name(), [fexpr()]} | {remote, fann(), [ftype()], ftype(), fexpr(), fun_name(), [fexpr()]} | {builtin, builtin(), [fexpr()]} | {con, arities(), tag(), [fexpr()]} @@ -80,7 +80,7 @@ %% The following (unapplied top-level functions/builtins and %% lambdas) are generated by the fcode compiler, but translated %% to closures by the lambda lifter. - | {def_u, fun_name(), arity()} + | {def_u, fann(), fun_name(), arity()} | {remote_u, fann(), [ftype()], ftype(), fexpr(), fun_name()} | {builtin_u, builtin(), arity()} | {builtin_u, builtin(), arity(), [fexpr()]} %% Typerep arguments to be added after normal args. @@ -652,8 +652,8 @@ expr_to_fcode(Env, _Type, {list, _, Es}) -> nil, Es); expr_to_fcode(Env, _Type, {app, _, {'..', _}, [A, B]}) -> - {def_u, FromTo, _} = resolve_fun(Env, ["ListInternal", "from_to"]), - {def, FromTo, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]}; + {def_u, Ann, FromTo, _} = resolve_fun(Env, ["ListInternal", "from_to"]), + {def, Ann, FromTo, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]}; expr_to_fcode(Env, _Type, {list_comp, _, Yield, []}) -> {op, '::', [expr_to_fcode(Env, Yield), nil]}; @@ -663,8 +663,8 @@ expr_to_fcode(Env, _Type, {list_comp, As, Yield, [{comprehension_bind, Pat = {ty Bind = {lam, [Arg], expr_to_fcode(Env1, {switch, As, {typed, As, {id, As, Arg}, PatType}, [{'case', As, Pat, [{guarded, As, [], {list_comp, As, Yield, Rest}}]}, {'case', As, {id, As, "_"}, [{guarded, As, [], {list, As, []}}]}]})}, - {def_u, FlatMap, _} = resolve_fun(Env, ["ListInternal", "flat_map"]), - {def, FlatMap, [Bind, expr_to_fcode(Env, BindExpr)]}; + {def_u, Ann, FlatMap, _} = resolve_fun(Env, ["ListInternal", "flat_map"]), + {def, Ann, FlatMap, [Bind, expr_to_fcode(Env, BindExpr)]}; expr_to_fcode(Env, Type, {list_comp, As, Yield, [{comprehension_if, _, Cond}|Rest]}) -> make_if(expr_to_fcode(Env, Cond), expr_to_fcode(Env, Type, {list_comp, As, Yield, Rest}), @@ -737,7 +737,7 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A {_, _} -> fcode_error({not_a_contract_type, Type}) end; {builtin_u, B, _Ar} -> builtin_to_fcode(state_layout(Env), B, FArgs); - {def_u, F, _Ar} -> {def, F, FArgs}; + {def_u, Ann, F, _Ar} -> {def, Ann, F, FArgs}; {remote_u, Ann, RArgsT, RRetT, Ct, RFun} -> {remote, Ann, RArgsT, RRetT, Ct, RFun, FArgs}; FFun -> %% FFun is a closure, with first component the function name and @@ -1135,7 +1135,7 @@ builtin_to_fcode(Layout, get_state, []) -> builtin_to_fcode(_Layout, require, [Cond, Msg]) -> make_if(Cond, {tuple, []}, {builtin, abort, [Msg]}); builtin_to_fcode(_Layout, chain_event, [Event]) -> - {def, event, [Event]}; + {def, [], event, [Event]}; builtin_to_fcode(_Layout, map_delete, [Key, Map]) -> {op, map_delete, [Map, Key]}; builtin_to_fcode(_Layout, map_member, [Key, Map]) -> @@ -1256,7 +1256,7 @@ lambda_lift_expr(Layout, {lam, Xs, Body}) -> FVs = free_vars({lam, Xs, Body}), make_closure(FVs, Xs, lambda_lift_expr(Layout, Body)); lambda_lift_expr(Layout, UExpr) when element(1, UExpr) == def_u; element(1, UExpr) == builtin_u -> - [Tag, F, Ar | _] = tuple_to_list(UExpr), + [Tag, _, F, Ar | _] = tuple_to_list(UExpr), ExtraArgs = case UExpr of {builtin_u, _, _, TypeArgs} -> TypeArgs; _ -> [] @@ -1265,7 +1265,7 @@ lambda_lift_expr(Layout, UExpr) when element(1, UExpr) == def_u; element(1, UExp Args = [{var, X} || X <- Xs] ++ ExtraArgs, Body = case Tag of builtin_u -> builtin_to_fcode(Layout, F, Args); - def_u -> {def, F, Args} + def_u -> {def, [], F, Args} end, make_closure([], Xs, Body); lambda_lift_expr(Layout, {remote_u, Ann, ArgsT, RetT, Ct, F}) -> @@ -1281,7 +1281,7 @@ lambda_lift_expr(Layout, Expr) -> nil -> Expr; {var, _} -> Expr; {closure, _, _, _} -> Expr; - {def, D, As} -> {def, D, lambda_lift_exprs(Layout, As)}; + {def, Ann, D, As} -> {def, Ann, D, lambda_lift_exprs(Layout, As)}; {builtin, B, As} -> {builtin, B, lambda_lift_exprs(Layout, As)}; {remote, Ann, ArgsT, RetT, Ct, F, As} -> {remote, Ann, ArgsT, RetT, lambda_lift_expr(Layout, Ct), F, lambda_lift_exprs(Layout, As)}; {con, Ar, C, As} -> {con, Ar, C, lambda_lift_exprs(Layout, As)}; @@ -1335,7 +1335,7 @@ optimize_fun(Fcode, Fun, Def = #{ body := Body0 }, Options) -> %% --- Inlining --- -spec inliner(fcode(), fun_name(), fexpr()) -> fexpr(). -inliner(Fcode, Fun, {def, Fun1, Args} = E) when Fun1 /= Fun -> +inliner(Fcode, Fun, {def, _, Fun1, Args} = E) when Fun1 /= Fun -> case should_inline(Fcode, Fun1) of false -> E; true -> inline(Fcode, Fun1, Args) @@ -1344,7 +1344,7 @@ inliner(_Fcode, _Fun, E) -> E. should_inline(_Fcode, _Fun1) -> false == list_to_atom("true"). %% Dialyzer -inline(_Fcode, Fun, Args) -> {def, Fun, Args}. %% TODO +inline(_Fcode, Fun, Args) -> {def, [], Fun, Args}. %% TODO %% --- Bind subexpressions --- @@ -1600,12 +1600,12 @@ read_only({set_proj, _, A, _, B}) -> read_only([A, B]); read_only({op, _, Es}) -> read_only(Es); read_only({get_state, _}) -> true; read_only({set_state, _, _, _}) -> false; -read_only({def_u, _, _}) -> true; +read_only({def_u, _, _, _}) -> true; read_only({remote_u, _, _, _, _, _}) -> true; read_only({builtin_u, _, _}) -> true; read_only({builtin_u, _, _, _}) -> true; read_only({lam, _, _}) -> true; -read_only({def, _, _}) -> false; %% TODO: purity analysis +read_only({def, _, _, _}) -> false; %% TODO: purity analysis read_only({remote, _, _, _, _, _, _}) -> false; read_only({builtin, _, _}) -> false; %% TODO: some builtins are read_only({switch, Split}) -> read_only(Split); @@ -1761,7 +1761,7 @@ resolve_fun(#{ fun_env := Funs, builtins := Builtin } = Env, Q) -> {not_found, not_found} -> internal_error({unbound_variable, Q}); {_, {B, none}} -> builtin_to_fcode(state_layout(Env), B, []); {_, {B, Ar}} -> {builtin_u, B, Ar}; - {{Fun, Ar}, _} -> {def_u, Fun, Ar} + {{Fun, Ar}, _} -> {def_u, [], Fun, Ar} end. init_fresh_names(Options) -> @@ -1828,8 +1828,8 @@ free_vars(Expr) -> {var, X} -> [X]; {lit, _} -> []; nil -> []; - {def, _, As} -> free_vars(As); - {def_u, _, _} -> []; + {def, _, _, As} -> free_vars(As); + {def_u, _, _, _} -> []; {remote, _, _, _, Ct, _, As} -> free_vars([Ct | As]); {remote_u, _, _, _, Ct, _} -> free_vars(Ct); {builtin, _, As} -> free_vars(As); @@ -1859,8 +1859,8 @@ used_defs(Expr) -> {var, _} -> []; {lit, _} -> []; nil -> []; - {def, F, As} -> lists:umerge([F], used_defs(As)); - {def_u, F, _} -> [F]; + {def, _, F, As} -> lists:umerge([F], used_defs(As)); + {def_u, _, F, _} -> [F]; {remote, _, _, _, Ct, _, As} -> used_defs([Ct | As]); {remote_u, _, _, _, Ct, _} -> used_defs(Ct); {builtin, _, As} -> used_defs(As); @@ -1890,8 +1890,8 @@ bottom_up(F, Env, Expr) -> {lit, _} -> Expr; nil -> Expr; {var, _} -> Expr; - {def, D, Es} -> {def, D, [bottom_up(F, Env, E) || E <- Es]}; - {def_u, _, _} -> Expr; + {def, Ann, D, Es} -> {def, Ann, D, [bottom_up(F, Env, E) || E <- Es]}; + {def_u, _, _, _} -> Expr; {builtin, B, Es} -> {builtin, B, [bottom_up(F, Env, E) || E <- Es]}; {builtin_u, _, _} -> Expr; {builtin_u, _, _, _} -> Expr; @@ -1948,8 +1948,8 @@ rename(Ren, Expr) -> {lit, _} -> Expr; nil -> nil; {var, X} -> {var, rename_var(Ren, X)}; - {def, D, Es} -> {def, D, [rename(Ren, E) || E <- Es]}; - {def_u, _, _} -> Expr; + {def, Ann, D, Es} -> {def, Ann, D, [rename(Ren, E) || E <- Es]}; + {def_u, _, _, _} -> Expr; {builtin, B, Es} -> {builtin, B, [rename(Ren, E) || E <- Es]}; {builtin_u, _, _} -> Expr; {builtin_u, _, _, _} -> Expr; @@ -2148,9 +2148,9 @@ pp_fexpr(nil) -> pp_text("[]"); pp_fexpr({var, X}) -> pp_text(X); pp_fexpr({def, Fun}) -> pp_fun_name(Fun); -pp_fexpr({def_u, Fun, Ar}) -> +pp_fexpr({def_u, _, Fun, Ar}) -> pp_beside([pp_fun_name(Fun), pp_text("/"), pp_int(Ar)]); -pp_fexpr({def, Fun, Args}) -> +pp_fexpr({def, _, Fun, Args}) -> pp_call(pp_fun_name(Fun), Args); pp_fexpr({con, _, I, []}) -> pp_beside(pp_text("C"), pp_int(I)); -- 2.30.2 From a027ac4f6ab3c10c6651184fb4f4a5df03de8102 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 5 Nov 2022 12:35:48 +0300 Subject: [PATCH 10/92] Add fann() to op --- src/aeso_ast_to_fcode.erl | 108 ++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 51 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 5514155..2ccc67a 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -70,7 +70,7 @@ | {tuple, [fexpr()]} | {proj, fann(), fexpr(), integer()} | {set_proj, fann(), fexpr(), integer(), fexpr()} %% tuple, field, new_value - | {op, op(), [fexpr()]} + | {op, fann(), op(), [fexpr()]} | {'let', var_name(), fexpr(), fexpr()} | {funcall, fann(), fexpr(), [fexpr()]} %% Call to unknown function | {closure, fann(), fun_name(), fexpr()} @@ -598,7 +598,7 @@ expr_to_fcode(Env, _Type, {tuple, _, Es}) -> expr_to_fcode(Env, Type, {proj, Ann, Rec = {typed, _, _, RecType}, {id, _, X}}) -> case RecType of {con, _, _} when X == "address" -> - {op, contract_to_address, [expr_to_fcode(Env, Rec)]}; + {op, to_fann(Ann), contract_to_address, [expr_to_fcode(Env, Rec)]}; {con, _, _} -> {fun_t, _, _, Args, Ret} = Type, FArgs = [type_to_fcode(Env, Arg) || Arg <- Args], @@ -648,15 +648,15 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) -> %% Lists expr_to_fcode(Env, _Type, {list, _, Es}) -> - lists:foldr(fun(E, L) -> {op, '::', [expr_to_fcode(Env, E), L]} end, + lists:foldr(fun(E, L) -> {op, to_fann(aeso_syntax:get_ann(E)), '::', [expr_to_fcode(Env, E), L]} end, nil, Es); expr_to_fcode(Env, _Type, {app, _, {'..', _}, [A, B]}) -> {def_u, Ann, FromTo, _} = resolve_fun(Env, ["ListInternal", "from_to"]), {def, Ann, FromTo, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]}; -expr_to_fcode(Env, _Type, {list_comp, _, Yield, []}) -> - {op, '::', [expr_to_fcode(Env, Yield), nil]}; +expr_to_fcode(Env, _Type, {list_comp, As, Yield, []}) -> + {op, to_fann(As), '::', [expr_to_fcode(Env, Yield), nil]}; expr_to_fcode(Env, _Type, {list_comp, As, Yield, [{comprehension_bind, Pat = {typed, _, _, PatType}, BindExpr}|Rest]}) -> Arg = fresh_name(), Env1 = bind_var(Env, Arg), @@ -705,12 +705,13 @@ expr_to_fcode(Env, _Type, Expr = {app, _, {Op, _}, [_, _]}) when Op == '&&'; Op expr_to_fcode(Env, Type, {app, Ann, {Op, _}, [A, B]}) when is_atom(Op) -> case Op of '|>' -> expr_to_fcode(Env, Type, {app, Ann, B, [A]}); - _ -> {op, Op, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]} + _ -> {op, to_fann(Ann), Op, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]} end; -expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) -> +expr_to_fcode(Env, _Type, {app, Ann, {Op, _}, [A]}) when is_atom(Op) -> + FAnn = to_fann(Ann), case Op of - '-' -> {op, '-', [{lit, {int, 0}}, expr_to_fcode(Env, A)]}; - '!' -> {op, '!', [expr_to_fcode(Env, A)]} + '-' -> {op, FAnn, '-', [{lit, {int, 0}}, expr_to_fcode(Env, A)]}; + '!' -> {op, FAnn, '!', [expr_to_fcode(Env, A)]} end; %% Function calls @@ -763,27 +764,28 @@ expr_to_fcode(Env, _Type, {map, _, Map, KVs}) -> ?make_let(Map1, expr_to_fcode(Env, Map), lists:foldr(fun(Fld, M) -> case Fld of - {field, _, [{map_get, _, K}], V} -> - {op, map_set, [M, expr_to_fcode(Env, K), expr_to_fcode(Env, V)]}; - {field_upd, _, [MapGet], {typed, _, {lam, _, [{arg, _, {id, _, Z}, _}], V}, _}} when element(1, MapGet) == map_get -> + {field, Ann, [{map_get, _, K}], V} -> + {op, to_fann(Ann), map_set, [M, expr_to_fcode(Env, K), expr_to_fcode(Env, V)]}; + {field_upd, Ann, [MapGet], {typed, _, {lam, _, [{arg, _, {id, _, Z}, _}], V}, _}} when element(1, MapGet) == map_get -> [map_get, _, K | Default] = tuple_to_list(MapGet), ?make_let(Key, expr_to_fcode(Env, K), begin %% Z might shadow Map1 or Key Z1 = fresh_name(), + FAnn = to_fann(Ann), GetExpr = case Default of - [] -> {op, map_get, [Map1, Key]}; - [D] -> {op, map_get_d, [Map1, Key, expr_to_fcode(Env, D)]} + [] -> {op, FAnn, map_get, [Map1, Key]}; + [D] -> {op, FAnn, map_get_d, [Map1, Key, expr_to_fcode(Env, D)]} end, {'let', Z1, GetExpr, - {op, map_set, [M, Key, rename([{Z, Z1}], expr_to_fcode(bind_var(Env, Z), V))]}} + {op, FAnn, map_set, [M, Key, rename([{Z, Z1}], expr_to_fcode(bind_var(Env, Z), V))]}} end) end end, Map1, KVs)); -expr_to_fcode(Env, _Type, {map_get, _, Map, Key}) -> - {op, map_get, [expr_to_fcode(Env, Map), expr_to_fcode(Env, Key)]}; -expr_to_fcode(Env, _Type, {map_get, _, Map, Key, Def}) -> - {op, map_get_d, [expr_to_fcode(Env, Map), expr_to_fcode(Env, Key), expr_to_fcode(Env, Def)]}; +expr_to_fcode(Env, _Type, {map_get, Ann, Map, Key}) -> + {op, to_fann(Ann), map_get, [expr_to_fcode(Env, Map), expr_to_fcode(Env, Key)]}; +expr_to_fcode(Env, _Type, {map_get, Ann, Map, Key, Def}) -> + {op, to_fann(Ann), map_get_d, [expr_to_fcode(Env, Map), expr_to_fcode(Env, Key), expr_to_fcode(Env, Def)]}; expr_to_fcode(Env, _Type, {lam, _, Args, Body}) -> GetArg = fun({arg, _, {id, _, X}, _}) -> X end, @@ -1137,20 +1139,24 @@ builtin_to_fcode(_Layout, require, [Cond, Msg]) -> builtin_to_fcode(_Layout, chain_event, [Event]) -> {def, [], event, [Event]}; builtin_to_fcode(_Layout, map_delete, [Key, Map]) -> - {op, map_delete, [Map, Key]}; + {op, get_fann(Map), map_delete, [Map, Key]}; builtin_to_fcode(_Layout, map_member, [Key, Map]) -> - {op, map_member, [Map, Key]}; + {op, get_fann(Map), map_member, [Map, Key]}; builtin_to_fcode(_Layout, map_lookup, [Key0, Map0]) -> ?make_let(Key, Key0, ?make_let(Map, Map0, - make_if({op, map_member, [Map, Key]}, - {con, [0, 1], 1, [{op, map_get, [Map, Key]}]}, + make_if({op, get_fann(Map), map_member, [Map, Key]}, + {con, [0, 1], 1, [{op, get_fann(Map), map_get, [Map, Key]}]}, {con, [0, 1], 0, []}))); builtin_to_fcode(_Layout, map_lookup_default, [Key, Map, Def]) -> - {op, map_get_d, [Map, Key, Def]}; + {op, get_fann(Map), map_get_d, [Map, Key, Def]}; builtin_to_fcode(_Layout, Builtin, Args) -> + FAnn = case Args of + [Arg | _] -> to_fann(aeso_syntax:get_ann(Arg)); + _ -> [] + end, case lists:member(Builtin, op_builtins()) of - true -> {op, Builtin, Args}; + true -> {op, FAnn, Builtin, Args}; false -> {builtin, Builtin, Args} end. @@ -1288,7 +1294,7 @@ lambda_lift_expr(Layout, Expr) -> {tuple, As} -> {tuple, lambda_lift_exprs(Layout, As)}; {proj, Ann, A, I} -> {proj, Ann, lambda_lift_expr(Layout, A), I}; {set_proj, Ann, A, I, B} -> {set_proj, Ann, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)}; - {op, Op, As} -> {op, Op, lambda_lift_exprs(Layout, As)}; + {op, Ann, Op, As} -> {op, Ann, Op, lambda_lift_exprs(Layout, As)}; {'let', X, A, B} -> {'let', X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)}; {funcall, Ann, A, Bs} -> {funcall, Ann, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)}; {set_state, Ann, R, A} -> {set_state, Ann, R, lambda_lift_expr(Layout, A)}; @@ -1392,9 +1398,9 @@ let_float(_, {proj, Ann, E, I}) -> pull_out_let({proj, Ann, {here, E}, I}); let_float(_, {set_proj, Ann, E, I, V}) -> pull_out_let({set_proj, Ann, {here, E}, I, {here, V}}); -let_float(_, {op, Op, Es}) -> +let_float(_, {op, Ann, Op, Es}) -> {Lets, Es1} = pull_out_let([{here, E} || E <- Es]), - let_bind(Lets, {op, Op, Es1}); + let_bind(Lets, {op, Ann, Op, Es1}); let_float(_, E) -> E. pull_out_let(Expr) when is_tuple(Expr) -> @@ -1535,14 +1541,14 @@ simpl_case(Env, E, [{'case', Pat, Body} | Alts]) -> end. -spec match_pat(fsplit_pat(), fexpr()) -> false | [{var_name(), fexpr()}]. -match_pat({tuple, Xs}, {tuple, Es}) -> lists:zip(Xs, Es); -match_pat({con, _, C, Xs}, {con, _, C, Es}) -> lists:zip(Xs, Es); -match_pat(L, {lit, L}) -> []; -match_pat(nil, nil) -> []; -match_pat({'::', X, Y}, {op, '::', [A, B]}) -> [{X, A}, {Y, B}]; -match_pat({var, X}, E) -> [{X, E}]; -match_pat({assign, X, P}, E) -> [{X, E}, {P, E}]; -match_pat(_, _) -> false. +match_pat({tuple, Xs}, {tuple, Es}) -> lists:zip(Xs, Es); +match_pat({con, _, C, Xs}, {con, _, C, Es}) -> lists:zip(Xs, Es); +match_pat(L, {lit, L}) -> []; +match_pat(nil, nil) -> []; +match_pat({'::', X, Y}, {op, _, '::', [A, B]}) -> [{X, A}, {Y, B}]; +match_pat({var, X}, E) -> [{X, E}]; +match_pat({assign, X, P}, E) -> [{X, E}, {P, E}]; +match_pat(_, _) -> false. constructor_form(Env, Expr) -> case Expr of @@ -1561,12 +1567,12 @@ constructor_form(Env, Expr) -> {tuple, Es} -> constructor_form(Env, lists:nth(I + 1, Es)); _ -> false end; - {con, _, _, _} -> Expr; - {tuple, _} -> Expr; - {lit, _} -> Expr; - nil -> Expr; - {op, '::', _} -> Expr; - _ -> false + {con, _, _, _} -> Expr; + {tuple, _} -> Expr; + {lit, _} -> Expr; + nil -> Expr; + {op, _, '::', _} -> Expr; + _ -> false end. %% --- Drop unused lets --- @@ -1597,7 +1603,7 @@ read_only({con, _, _, Es}) -> read_only(Es); read_only({tuple, Es}) -> read_only(Es); read_only({proj, _, E, _}) -> read_only(E); read_only({set_proj, _, A, _, B}) -> read_only([A, B]); -read_only({op, _, Es}) -> read_only(Es); +read_only({op, _, _, Es}) -> read_only(Es); read_only({get_state, _}) -> true; read_only({set_state, _, _, _}) -> false; read_only({def_u, _, _, _}) -> true; @@ -1839,7 +1845,7 @@ free_vars(Expr) -> {tuple, As} -> free_vars(As); {proj, _, A, _} -> free_vars(A); {set_proj, _, A, _, B} -> free_vars([A, B]); - {op, _, As} -> free_vars(As); + {op, _, _, As} -> free_vars(As); {'let', X, A, B} -> free_vars([A, {lam, [X], B}]); {funcall, _, A, Bs} -> free_vars([A | Bs]); {set_state, _, _, A} -> free_vars(A); @@ -1870,7 +1876,7 @@ used_defs(Expr) -> {tuple, As} -> used_defs(As); {proj, _, A, _} -> used_defs(A); {set_proj, _, A, _, B} -> used_defs([A, B]); - {op, _, As} -> used_defs(As); + {op, _, _, As} -> used_defs(As); {'let', _, A, B} -> used_defs([A, B]); {funcall, _, A, Bs} -> used_defs([A | Bs]); {set_state, _, _, A} -> used_defs(A); @@ -1901,7 +1907,7 @@ bottom_up(F, Env, Expr) -> {tuple, Es} -> {tuple, [bottom_up(F, Env, E) || E <- Es]}; {proj, Ann, E, I} -> {proj, Ann, bottom_up(F, Env, E), I}; {set_proj, Ann, R, I, E} -> {set_proj, Ann, bottom_up(F, Env, R), I, bottom_up(F, Env, E)}; - {op, Op, Es} -> {op, Op, [bottom_up(F, Env, E) || E <- Es]}; + {op, Ann, Op, Es} -> {op, Ann, Op, [bottom_up(F, Env, E) || E <- Es]}; {funcall, Ann, Fun, Es} -> {funcall, Ann, bottom_up(F, Env, Fun), [bottom_up(F, Env, E) || E <- Es]}; {set_state, Ann, R, E} -> {set_state, Ann, R, bottom_up(F, Env, E)}; {get_state, _} -> Expr; @@ -1959,7 +1965,7 @@ rename(Ren, Expr) -> {tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]}; {proj, Ann, E, I} -> {proj, Ann, rename(Ren, E), I}; {set_proj, Ann, R, I, E} -> {set_proj, Ann, rename(Ren, R), I, rename(Ren, E)}; - {op, Op, Es} -> {op, Op, [rename(Ren, E) || E <- Es]}; + {op, Ann, Op, Es} -> {op, Ann, Op, [rename(Ren, E) || E <- Es]}; {funcall, Ann, Fun, Es} -> {funcall, Ann, rename(Ren, Fun), [rename(Ren, E) || E <- Es]}; {set_state, Ann, R, E} -> {set_state, Ann, R, rename(Ren, E)}; {get_state, _} -> Expr; @@ -2172,17 +2178,17 @@ pp_fexpr({closure, _, Fun, ClEnv}) -> pp_call(pp_text("__CLOSURE__"), [{def, Fun} | FVs]); pp_fexpr({set_proj, _, E, I, A}) -> pp_beside(pp_fexpr(E), pp_braces(pp_beside([pp_int(I), pp_text(" = "), pp_fexpr(A)]))); -pp_fexpr({op, Op, [A, B] = Args}) -> +pp_fexpr({op, _, Op, [A, B] = Args}) -> case is_infix(Op) of false -> pp_call(pp_text(Op), Args); true -> pp_parens(pp_par([pp_fexpr(A), pp_text(Op), pp_fexpr(B)])) end; -pp_fexpr({op, Op, [A] = Args}) -> +pp_fexpr({op, _, Op, [A] = Args}) -> case is_infix(Op) of false -> pp_call(pp_text(Op), Args); true -> pp_parens(pp_par([pp_text(Op), pp_fexpr(A)])) end; -pp_fexpr({op, Op, As}) -> +pp_fexpr({op, _, Op, As}) -> pp_beside(pp_text(Op), pp_fexpr({tuple, As})); pp_fexpr({'let', _, _, _} = Expr) -> Lets = fun Lets({'let', Y, C, D}) -> @@ -2254,7 +2260,7 @@ pp_case({'case', Pat, Split}) -> prettypr:nest(2, pp_split(Split))]). pp_pat({tuple, Xs}) -> pp_fexpr({tuple, [{var, X} || X <- Xs]}); -pp_pat({'::', X, Xs}) -> pp_fexpr({op, '::', [{var, X}, {var, Xs}]}); +pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, X}, {var, Xs}]}); pp_pat({con, As, I, Xs}) -> pp_fexpr({con, As, I, [{var, X} || X <- Xs]}); pp_pat({var, X}) -> pp_fexpr({var, X}); pp_pat(P = {Tag, _}) when Tag == bool; Tag == int; Tag == string -- 2.30.2 From 48136ef719f5da7f6a9d3b864eaa462ca9ce8b50 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 5 Nov 2022 13:16:20 +0300 Subject: [PATCH 11/92] Add fann() to let --- src/aeso_ast_to_fcode.erl | 87 ++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 2ccc67a..5d2e5be 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -71,7 +71,7 @@ | {proj, fann(), fexpr(), integer()} | {set_proj, fann(), fexpr(), integer(), fexpr()} %% tuple, field, new_value | {op, fann(), op(), [fexpr()]} - | {'let', var_name(), fexpr(), fexpr()} + | {'let', fann(), var_name(), fexpr(), fexpr()} | {funcall, fann(), fexpr(), [fexpr()]} %% Call to unknown function | {closure, fann(), fun_name(), fexpr()} | {switch, fsplit()} @@ -524,11 +524,11 @@ make_let(Expr, Body) -> {lit, {bool, _}} -> Body(Expr); _ -> X = fresh_name(), - {'let', X, Expr, Body({var, X})} + {'let', get_fann(Expr), X, Expr, Body({var, X})} end. let_bind(X, {var, Y}, Body) -> rename([{X, Y}], Body); -let_bind(X, Expr, Body) -> {'let', X, Expr, Body}. +let_bind(X, Expr, Body) -> {'let', get_fann(Expr), X, Expr, Body}. let_bind(Binds, Body) -> lists:foldr(fun({X, E}, Rest) -> let_bind(X, E, Rest) end, @@ -620,23 +620,24 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, _Ann, Fields}) -> end, make_tuple(lists:map(FVal, FieldTypes)); -expr_to_fcode(Env, {record_t, [FieldT]}, {record, _Ann, Rec, Fields}) -> +expr_to_fcode(Env, {record_t, [FieldT]}, {record, Ann, Rec, Fields}) -> case field_value(FieldT, Fields) of false -> expr_to_fcode(Env, Rec); {set, E} -> expr_to_fcode(Env, E); - {upd, Z, E} -> {'let', Z, expr_to_fcode(Env, Rec), expr_to_fcode(bind_var(Env, Z), E)} + {upd, Z, E} -> {'let', to_fann(Ann), Z, expr_to_fcode(Env, Rec), expr_to_fcode(bind_var(Env, Z), E)} end; expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) -> X = fresh_name(), - Proj = fun(I) -> {proj, to_fann(Ann), {var, X}, I - 1} end, + FAnn = to_fann(Ann), + Proj = fun(I) -> {proj, FAnn, {var, X}, I - 1} end, Comp = fun({I, false}) -> Proj(I); ({_, {set, E}}) -> expr_to_fcode(Env, E); - ({I, {upd, Z, E}}) -> {'let', Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)} + ({I, {upd, Z, E}}) -> {'let', FAnn, Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)} end, Set = fun({_, false}, R) -> R; - ({I, {set, E}}, R) -> {set_proj, to_fann(Ann), R, I - 1, expr_to_fcode(Env, E)}; - ({I, {upd, Z, E}}, R) -> {set_proj, to_fann(Ann), R, I - 1, - {'let', Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)}} + ({I, {set, E}}, R) -> {set_proj, FAnn, R, I - 1, expr_to_fcode(Env, E)}; + ({I, {upd, Z, E}}, R) -> {set_proj, FAnn, R, I - 1, + {'let', FAnn, Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)}} end, Expand = length(Fields) == length(FieldTypes), Updates = [ {I, field_value(FT, Fields)} || {I, FT} <- indexed(FieldTypes) ], @@ -644,7 +645,7 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) -> true -> {tuple, lists:map(Comp, Updates)}; false -> lists:foldr(Set, {var, X}, Updates) end, - {'let', X, expr_to_fcode(Env, Rec), Body}; + {'let', FAnn, X, expr_to_fcode(Env, Rec), Body}; %% Lists expr_to_fcode(Env, _Type, {list, _, Es}) -> @@ -682,7 +683,7 @@ expr_to_fcode(Env, _Type, {'if', _, Cond, Then, Else}) -> expr_to_fcode(Env, Else)); %% Switch -expr_to_fcode(Env, _, S = {switch, _, Expr = {typed, _, E, Type}, Alts}) -> +expr_to_fcode(Env, _, S = {switch, Ann, Expr = {typed, _, E, Type}, Alts}) -> Switch = fun(X) -> {switch, alts_to_fcode(Env, type_to_fcode(Env, Type), X, Alts, S)} end, @@ -690,7 +691,7 @@ expr_to_fcode(Env, _, S = {switch, _, Expr = {typed, _, E, Type}, Alts}) -> {id, _, X} -> Switch(X); _ -> X = fresh_name(), - {'let', X, expr_to_fcode(Env, Expr), + {'let', to_fann(Ann), X, expr_to_fcode(Env, Expr), Switch(X)} end; @@ -748,7 +749,7 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A case FFun of {var, X} -> Call(X); _ -> X = fresh_name(), - {'let', X, FFun, Call(X)} + {'let', FAnn, X, FFun, Call(X)} end end; @@ -778,7 +779,7 @@ expr_to_fcode(Env, _Type, {map, _, Map, KVs}) -> [] -> {op, FAnn, map_get, [Map1, Key]}; [D] -> {op, FAnn, map_get_d, [Map1, Key, expr_to_fcode(Env, D)]} end, - {'let', Z1, GetExpr, + {'let', FAnn, Z1, GetExpr, {op, FAnn, map_set, [M, Key, rename([{Z, Z1}], expr_to_fcode(bind_var(Env, Z), V))]}} end) end end, Map1, KVs)); @@ -801,14 +802,14 @@ make_if({var, X}, Then, Else) -> {'case', {bool, true}, {nosplit, Then}}]}}; make_if(Cond, Then, Else) -> X = fresh_name(), - {'let', X, Cond, make_if({var, X}, Then, Else)}. + {'let', get_fann(Cond), X, Cond, make_if({var, X}, Then, Else)}. make_if_no_else({var, X}, Then) -> {switch, {split, boolean, X, [{'case', {bool, true}, {nosplit, Then}}]}}; make_if_no_else(Cond, Then) -> X = fresh_name(), - {'let', X, Cond, make_if_no_else({var, X}, Then)}. + {'let', get_fann(Cond), X, Cond, make_if_no_else({var, X}, Then)}. -spec make_tuple([fexpr()]) -> fexpr(). make_tuple([E]) -> E; @@ -1073,15 +1074,15 @@ decision_tree_to_fcode(true) -> {lit, {bool, true}}; decision_tree_to_fcode({atom, B}) -> B; decision_tree_to_fcode({'if', A, Then, Else}) -> X = fresh_name(), - {'let', X, A, + {'let', [], X, A, {switch, {split, boolean, X, [{'case', {bool, false}, {nosplit, decision_tree_to_fcode(Else)}}, {'case', {bool, true}, {nosplit, decision_tree_to_fcode(Then)}}]}}}. %% -- Statements -- -spec stmts_to_fcode(env(), [aeso_syntax:stmt()]) -> fexpr(). -stmts_to_fcode(Env, [{letval, _, {typed, _, {id, _, X}, _}, Expr} | Stmts]) -> - {'let', X, expr_to_fcode(Env, Expr), stmts_to_fcode(bind_var(Env, X), Stmts)}; +stmts_to_fcode(Env, [{letval, Ann, {typed, _, {id, _, X}, _}, Expr} | Stmts]) -> + {'let', to_fann(Ann), X, expr_to_fcode(Env, Expr), stmts_to_fcode(bind_var(Env, X), Stmts)}; stmts_to_fcode(Env, [{letval, Ann, Pat, Expr} | Stmts]) -> expr_to_fcode(Env, {switch, Ann, Expr, [{'case', Ann, Pat, [{guarded, Ann, [], {block, Ann, Stmts}}]}]}); stmts_to_fcode(Env, [{letfun, Ann, {id, _, X}, Args, _Type, [{guarded, _, [], Expr}]} | Stmts]) -> @@ -1089,12 +1090,12 @@ stmts_to_fcode(Env, [{letfun, Ann, {id, _, X}, Args, _Type, [{guarded, _, [], Ex {typed, Ann1, Id, T} -> {arg, Ann1, Id, T}; _ -> internal_error({bad_arg, Arg}) %% pattern matching has been desugared end || Arg <- Args ], - {'let', X, expr_to_fcode(Env, {lam, Ann, LamArgs, Expr}), + {'let', to_fann(Ann), X, expr_to_fcode(Env, {lam, Ann, LamArgs, Expr}), stmts_to_fcode(bind_var(Env, X), Stmts)}; stmts_to_fcode(Env, [Expr]) -> expr_to_fcode(Env, Expr); stmts_to_fcode(Env, [Expr | Stmts]) -> - {'let', "_", expr_to_fcode(Env, Expr), stmts_to_fcode(Env, Stmts)}. + {'let', to_fann(aeso_syntax:get_ann(Expr)), "_", expr_to_fcode(Env, Expr), stmts_to_fcode(Env, Stmts)}. %% -- Builtins -- @@ -1122,7 +1123,7 @@ set_state({reg, R}, Val) -> set_state({tuple, Ls}, Val) -> ?make_let(X, Val, lists:foldr(fun({I, L}, Code) -> - {'let', "_", set_state(L, {proj, get_fann(Val), X, I - 1}), Code} + {'let', [], "_", set_state(L, {proj, get_fann(Val), X, I - 1}), Code} end, {tuple, []}, indexed(Ls))). get_state({reg, R}) -> @@ -1246,7 +1247,7 @@ lifted_fun([Z], Xs, Body) -> body => Body }; lifted_fun(FVs, Xs, Body) -> Z = "%env", - Proj = fun({I, Y}, E) -> {'let', Y, {proj, get_fann(Body), {var, Z}, I - 1}, E} end, + Proj = fun({I, Y}, E) -> {'let', get_fann(Body), Y, {proj, get_fann(Body), {var, Z}, I - 1}, E} end, #{ attrs => [private], args => [{Z, any} | [{X, any} || X <- Xs]], return => any, @@ -1295,7 +1296,7 @@ lambda_lift_expr(Layout, Expr) -> {proj, Ann, A, I} -> {proj, Ann, lambda_lift_expr(Layout, A), I}; {set_proj, Ann, A, I, B} -> {set_proj, Ann, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)}; {op, Ann, Op, As} -> {op, Ann, Op, lambda_lift_exprs(Layout, As)}; - {'let', X, A, B} -> {'let', X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)}; + {'let', Ann, X, A, B} -> {'let', Ann, X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)}; {funcall, Ann, A, Bs} -> {funcall, Ann, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)}; {set_state, Ann, R, A} -> {set_state, Ann, R, lambda_lift_expr(Layout, A)}; {get_state, _} -> Expr; @@ -1392,8 +1393,8 @@ inline_local_functions(_, Expr) -> Expr. let_floating(Expr) -> bottom_up(fun let_float/2, Expr). -let_float(_, {'let', X, E, Body}) -> - pull_out_let({'let', X, {here, E}, Body}); +let_float(_, {'let', Ann, X, E, Body}) -> + pull_out_let({'let', Ann, X, {here, E}, Body}); let_float(_, {proj, Ann, E, I}) -> pull_out_let({proj, Ann, {here, E}, I}); let_float(_, {set_proj, Ann, E, I, V}) -> @@ -1424,7 +1425,7 @@ pull_out_let(Es) when is_list(Es) -> %% Also renames the variables to fresh names let_view(E) -> let_view(E, [], []). -let_view({'let', X, E, Rest}, Ren, Lets) -> +let_view({'let', _, X, E, Rest}, Ren, Lets) -> Z = fresh_name(), let_view(Rest, [{X, Z} | Ren], [{Z, rename(Ren, E)} | Lets]); let_view(E, Ren, Lets) -> @@ -1440,7 +1441,7 @@ simplifier(Expr) -> %% (e₀, .., en).i -> %% let _ = e₀ in .. let x = ei in .. let _ = en in x -simplify(_Env, {proj, _, {tuple, Es}, I}) -> +simplify(_Env, {proj, FAnn, {tuple, Es}, I}) -> It = lists:nth(I + 1, Es), X = fresh_name(), Dup = safe_to_duplicate(It), @@ -1449,12 +1450,12 @@ simplify(_Env, {proj, _, {tuple, Es}, I}) -> fun({J, E}, Rest) when I == J -> case Dup of true -> Rest; - false -> {'let', X, E, Rest} + false -> {'let', FAnn, X, E, Rest} end; ({_, E}, Rest) -> case read_only(E) of true -> Rest; - false -> {'let', "_", E, Rest} + false -> {'let', FAnn, "_", E, Rest} end end, Val, indexed(Es)); @@ -1579,10 +1580,10 @@ constructor_form(Env, Expr) -> drop_unused_lets(Expr) -> bottom_up(fun drop_unused_lets/2, Expr). -drop_unused_lets(_, {'let', X, E, Body} = Expr) -> +drop_unused_lets(_, {'let', Ann, X, E, Body} = Expr) -> case {read_only(E), not lists:member(X, free_vars(Body))} of {true, true} -> Body; - {false, true} -> {'let', "_", E, Body}; + {false, true} -> {'let', Ann, "_", E, Body}; _ -> Expr end; drop_unused_lets(_, Expr) -> Expr. @@ -1618,7 +1619,7 @@ read_only({switch, Split}) -> read_only(Split); read_only({split, _, _, Cases}) -> read_only(Cases); read_only({nosplit, E}) -> read_only(E); read_only({'case', _, Split}) -> read_only(Split); -read_only({'let', _, A, B}) -> read_only([A, B]); +read_only({'let', _, _, A, B}) -> read_only([A, B]); read_only({funcall, _, _, _}) -> false; read_only({closure, _, _, _}) -> internal_error(no_closures_here); read_only(Es) when is_list(Es) -> lists:all(fun read_only/1, Es). @@ -1846,7 +1847,7 @@ free_vars(Expr) -> {proj, _, A, _} -> free_vars(A); {set_proj, _, A, _, B} -> free_vars([A, B]); {op, _, _, As} -> free_vars(As); - {'let', X, A, B} -> free_vars([A, {lam, [X], B}]); + {'let', _, X, A, B} -> free_vars([A, {lam, [X], B}]); {funcall, _, A, Bs} -> free_vars([A | Bs]); {set_state, _, _, A} -> free_vars(A); {get_state, _} -> []; @@ -1877,7 +1878,7 @@ used_defs(Expr) -> {proj, _, A, _} -> used_defs(A); {set_proj, _, A, _, B} -> used_defs([A, B]); {op, _, _, As} -> used_defs(As); - {'let', _, A, B} -> used_defs([A, B]); + {'let', _, _, A, B} -> used_defs([A, B]); {funcall, _, A, Bs} -> used_defs([A | Bs]); {set_state, _, _, A} -> used_defs(A); {get_state, _} -> []; @@ -1914,7 +1915,7 @@ bottom_up(F, Env, Expr) -> {closure, Ann, F, CEnv} -> {closure, Ann, F, bottom_up(F, Env, CEnv)}; {switch, Split} -> {switch, bottom_up(F, Env, Split)}; {lam, Xs, B} -> {lam, Xs, bottom_up(F, Env, B)}; - {'let', X, E, Body} -> + {'let', Ann, X, E, Body} -> E1 = bottom_up(F, Env, E), %% Always freshen user variables to avoid shadowing issues. ShouldFreshen = fun(Y = "%" ++ _) -> maps:is_key(Y, Env); @@ -1923,10 +1924,10 @@ bottom_up(F, Env, Expr) -> true -> Z = fresh_name_save(X), Env1 = Env#{ Z => E1 }, - {'let', Z, E1, bottom_up(F, Env1, rename([{X, Z}], Body))}; + {'let', Ann, Z, E1, bottom_up(F, Env1, rename([{X, Z}], Body))}; false -> Env1 = Env#{ X => E1 }, - {'let', X, E1, bottom_up(F, Env1, Body)} + {'let', Ann, X, E1, bottom_up(F, Env1, Body)} end; {split, Type, X, Cases} -> {split, Type, X, [bottom_up(F, Env, Case) || Case <- Cases]}; {nosplit, E} -> {nosplit, bottom_up(F, Env, E)}; @@ -1974,9 +1975,9 @@ rename(Ren, Expr) -> {lam, Xs, B} -> {Zs, Ren1} = rename_bindings(Ren, Xs), {lam, Zs, rename(Ren1, B)}; - {'let', X, E, Body} -> + {'let', Ann, X, E, Body} -> {Z, Ren1} = rename_binding(Ren, X), - {'let', Z, rename(Ren, E), rename(Ren1, Body)} + {'let', Ann, Z, rename(Ren, E), rename(Ren1, Body)} end. rename_var(Ren, X) -> proplists:get_value(X, Ren, X). @@ -2190,8 +2191,8 @@ pp_fexpr({op, _, Op, [A] = Args}) -> end; pp_fexpr({op, _, Op, As}) -> pp_beside(pp_text(Op), pp_fexpr({tuple, As})); -pp_fexpr({'let', _, _, _} = Expr) -> - Lets = fun Lets({'let', Y, C, D}) -> +pp_fexpr({'let', _, _, _, _} = Expr) -> + Lets = fun Lets({'let', _, Y, C, D}) -> {Ls, E} = Lets(D), {[{Y, C} | Ls], E}; Lets(E) -> {[], E} end, -- 2.30.2 From 3f129b3b04331a42e784dc605562ae1434cc15a9 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 5 Nov 2022 13:25:55 +0300 Subject: [PATCH 12/92] Add fann() to lam --- src/aeso_ast_to_fcode.erl | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 5d2e5be..51c1114 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -84,7 +84,7 @@ | {remote_u, fann(), [ftype()], ftype(), fexpr(), fun_name()} | {builtin_u, builtin(), arity()} | {builtin_u, builtin(), arity(), [fexpr()]} %% Typerep arguments to be added after normal args. - | {lam, [var_name()], fexpr()}. + | {lam, fann(), [var_name()], fexpr()}. -type fsplit() :: {split, ftype(), var_name(), [fcase()]} | {nosplit, fexpr()}. @@ -661,9 +661,9 @@ expr_to_fcode(Env, _Type, {list_comp, As, Yield, []}) -> expr_to_fcode(Env, _Type, {list_comp, As, Yield, [{comprehension_bind, Pat = {typed, _, _, PatType}, BindExpr}|Rest]}) -> Arg = fresh_name(), Env1 = bind_var(Env, Arg), - Bind = {lam, [Arg], expr_to_fcode(Env1, {switch, As, {typed, As, {id, As, Arg}, PatType}, - [{'case', As, Pat, [{guarded, As, [], {list_comp, As, Yield, Rest}}]}, - {'case', As, {id, As, "_"}, [{guarded, As, [], {list, As, []}}]}]})}, + Bind = {lam, to_fann(As), [Arg], expr_to_fcode(Env1, {switch, As, {typed, As, {id, As, Arg}, PatType}, + [{'case', As, Pat, [{guarded, As, [], {list_comp, As, Yield, Rest}}]}, + {'case', As, {id, As, "_"}, [{guarded, As, [], {list, As, []}}]}]})}, {def_u, Ann, FlatMap, _} = resolve_fun(Env, ["ListInternal", "flat_map"]), {def, Ann, FlatMap, [Bind, expr_to_fcode(Env, BindExpr)]}; expr_to_fcode(Env, Type, {list_comp, As, Yield, [{comprehension_if, _, Cond}|Rest]}) -> @@ -788,10 +788,10 @@ expr_to_fcode(Env, _Type, {map_get, Ann, Map, Key}) -> expr_to_fcode(Env, _Type, {map_get, Ann, Map, Key, Def}) -> {op, to_fann(Ann), map_get_d, [expr_to_fcode(Env, Map), expr_to_fcode(Env, Key), expr_to_fcode(Env, Def)]}; -expr_to_fcode(Env, _Type, {lam, _, Args, Body}) -> +expr_to_fcode(Env, _Type, {lam, Ann, Args, Body}) -> GetArg = fun({arg, _, {id, _, X}, _}) -> X end, Xs = lists:map(GetArg, Args), - {lam, Xs, expr_to_fcode(bind_vars(Env, Xs), Body)}; + {lam, to_fann(Ann), Xs, expr_to_fcode(bind_vars(Env, Xs), Body)}; expr_to_fcode(_Env, Type, Expr) -> error({todo, {Expr, ':', Type}}). @@ -1259,8 +1259,8 @@ make_closure(FVs, Xs, Body) -> Tup = fun([Y]) -> Y; (Ys) -> {tuple, Ys} end, {closure, get_fann(Body), Fun, Tup([{var, Y} || Y <- FVs])}. -lambda_lift_expr(Layout, {lam, Xs, Body}) -> - FVs = free_vars({lam, Xs, Body}), +lambda_lift_expr(Layout, L = {lam, _, Xs, Body}) -> + FVs = free_vars(L), make_closure(FVs, Xs, lambda_lift_expr(Layout, Body)); lambda_lift_expr(Layout, UExpr) when element(1, UExpr) == def_u; element(1, UExpr) == builtin_u -> [Tag, _, F, Ar | _] = tuple_to_list(UExpr), @@ -1384,8 +1384,8 @@ inline_local_functions(Expr) -> inline_local_functions(Env, {funcall, _, {proj, _, {var, Y}, 0}, [{proj, _, {var, Y}, 1} | Args]} = Expr) -> %% TODO: Don't always inline local funs? case maps:get(Y, Env, free) of - {lam, Xs, Body} -> let_bind(lists:zip(Xs, Args), Body); - _ -> Expr + {lam, _, Xs, Body} -> let_bind(lists:zip(Xs, Args), Body); + _ -> Expr end; inline_local_functions(_, Expr) -> Expr. @@ -1611,7 +1611,7 @@ read_only({def_u, _, _, _}) -> true; read_only({remote_u, _, _, _, _, _}) -> true; read_only({builtin_u, _, _}) -> true; read_only({builtin_u, _, _, _}) -> true; -read_only({lam, _, _}) -> true; +read_only({lam, _, _, _}) -> true; read_only({def, _, _, _}) -> false; %% TODO: purity analysis read_only({remote, _, _, _, _, _, _}) -> false; read_only({builtin, _, _}) -> false; %% TODO: some builtins are @@ -1847,11 +1847,11 @@ free_vars(Expr) -> {proj, _, A, _} -> free_vars(A); {set_proj, _, A, _, B} -> free_vars([A, B]); {op, _, _, As} -> free_vars(As); - {'let', _, X, A, B} -> free_vars([A, {lam, [X], B}]); + {'let', Ann, X, A, B} -> free_vars([A, {lam, Ann, [X], B}]); {funcall, _, A, Bs} -> free_vars([A | Bs]); {set_state, _, _, A} -> free_vars(A); {get_state, _} -> []; - {lam, Xs, B} -> free_vars(B) -- lists:sort(Xs); + {lam, _, Xs, B} -> free_vars(B) -- lists:sort(Xs); {closure, _, _, A} -> free_vars(A); {switch, A} -> free_vars(A); {split, _, X, As} -> free_vars([{var, X} | As]); @@ -1882,7 +1882,7 @@ used_defs(Expr) -> {funcall, _, A, Bs} -> used_defs([A | Bs]); {set_state, _, _, A} -> used_defs(A); {get_state, _} -> []; - {lam, _, B} -> used_defs(B); + {lam, _, _, B} -> used_defs(B); {closure, _, F, A} -> lists:umerge([F], used_defs(A)); {switch, A} -> used_defs(A); {split, _, _, As} -> used_defs(As); @@ -1914,7 +1914,7 @@ bottom_up(F, Env, Expr) -> {get_state, _} -> Expr; {closure, Ann, F, CEnv} -> {closure, Ann, F, bottom_up(F, Env, CEnv)}; {switch, Split} -> {switch, bottom_up(F, Env, Split)}; - {lam, Xs, B} -> {lam, Xs, bottom_up(F, Env, B)}; + {lam, Ann, Xs, B} -> {lam, Ann, Xs, bottom_up(F, Env, B)}; {'let', Ann, X, E, Body} -> E1 = bottom_up(F, Env, E), %% Always freshen user variables to avoid shadowing issues. @@ -1972,9 +1972,9 @@ rename(Ren, Expr) -> {get_state, _} -> Expr; {closure, Ann, F, Env} -> {closure, Ann, F, rename(Ren, Env)}; {switch, Split} -> {switch, rename_split(Ren, Split)}; - {lam, Xs, B} -> + {lam, Ann, Xs, B} -> {Zs, Ren1} = rename_bindings(Ren, Xs), - {lam, Zs, rename(Ren1, B)}; + {lam, Ann, Zs, rename(Ren1, B)}; {'let', Ann, X, E, Body} -> {Z, Ren1} = rename_binding(Ren, X), {'let', Ann, Z, rename(Ren, E), rename(Ren1, Body)} @@ -2168,7 +2168,7 @@ pp_fexpr({tuple, Es}) -> pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_fexpr(E) || E <- Es]))); pp_fexpr({proj, _, E, I}) -> pp_beside([pp_fexpr(E), pp_text("."), pp_int(I)]); -pp_fexpr({lam, Xs, A}) -> +pp_fexpr({lam, _, Xs, A}) -> pp_par([pp_fexpr({tuple, [{var, X} || X <- Xs]}), pp_text("=>"), prettypr:nest(2, pp_fexpr(A))]); pp_fexpr({closure, _, Fun, ClEnv}) -> -- 2.30.2 From 2d4e1d702603b25663787fd254ec05279f2a72c2 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 5 Nov 2022 14:22:11 +0300 Subject: [PATCH 13/92] Add fann() to builtin_u --- src/aeso_ast_to_fcode.erl | 146 +++++++++++++++++++------------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 51c1114..e5b989b 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -82,8 +82,8 @@ %% to closures by the lambda lifter. | {def_u, fann(), fun_name(), arity()} | {remote_u, fann(), [ftype()], ftype(), fexpr(), fun_name()} - | {builtin_u, builtin(), arity()} - | {builtin_u, builtin(), arity(), [fexpr()]} %% Typerep arguments to be added after normal args. + | {builtin_u, fann(), builtin(), arity()} + | {builtin_u, fann(), builtin(), arity(), [fexpr()]} %% Typerep arguments to be added after normal args. | {lam, fann(), [var_name()], fexpr()}. -type fsplit() :: {split, ftype(), var_name(), [fcase()]} @@ -557,25 +557,25 @@ expr_to_fcode(_Env, _Type, {bytes, _, B}) -> {lit, {bytes, B}}; expr_to_fcode(Env, _Type, {id, _, X}) -> resolve_var(Env, [X]); expr_to_fcode(Env, Type, {qid, _, X}) -> case resolve_var(Env, X) of - {builtin_u, B, Ar} when B =:= oracle_query; - B =:= oracle_get_question; - B =:= oracle_get_answer; - B =:= oracle_respond; - B =:= oracle_register; - B =:= oracle_check; - B =:= oracle_check_query -> + {builtin_u, Ann, B, Ar} when B =:= oracle_query; + B =:= oracle_get_question; + B =:= oracle_get_answer; + B =:= oracle_respond; + B =:= oracle_register; + B =:= oracle_check; + B =:= oracle_check_query -> OType = get_oracle_type(B, Type), {oracle, QType, RType} = type_to_fcode(Env, OType), TypeArgs = [{lit, {typerep, QType}}, {lit, {typerep, RType}}], - {builtin_u, B, Ar, TypeArgs}; - {builtin_u, B = aens_resolve, Ar} -> + {builtin_u, Ann, B, Ar, TypeArgs}; + {builtin_u, Ann, B = aens_resolve, Ar} -> {fun_t, _, _, _, ResType} = Type, AensType = type_to_fcode(Env, ResType), TypeArgs = [{lit, {typerep, AensType}}], - {builtin_u, B, Ar, TypeArgs}; - {builtin_u, B = bytes_split, Ar} -> + {builtin_u, Ann, B, Ar, TypeArgs}; + {builtin_u, Ann, B = bytes_split, Ar} -> {fun_t, _, _, _, {tuple_t, _, [{bytes_t, _, N}, _]}} = Type, - {builtin_u, B, Ar, [{lit, {int, N}}]}; + {builtin_u, Ann, B, Ar, [{lit, {int, N}}]}; Other -> Other end; @@ -720,8 +720,8 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A Args1 = get_named_args(NamedArgsT, Args), FArgs = [expr_to_fcode(Env, Arg) || Arg <- Args1], case expr_to_fcode(Env, Fun) of - {builtin_u, B, _Ar, TypeArgs} -> builtin_to_fcode(state_layout(Env), B, FArgs ++ TypeArgs); - {builtin_u, chain_clone, _Ar} -> + {builtin_u, Ann, B, _Ar, TypeArgs} -> builtin_to_fcode(state_layout(Env), B, FArgs ++ TypeArgs); + {builtin_u, Ann, chain_clone, _Ar} -> case ArgsT of var_args -> fcode_error({var_args_not_set, FunE}); _ -> @@ -730,7 +730,7 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A FInitArgsT = aeb_fate_data:make_typerep([type_to_fcode(Env, T) || T <- ArgsT]), builtin_to_fcode(state_layout(Env), chain_clone, [{lit, FInitArgsT}|FArgs]) end; - {builtin_u, chain_create, _Ar} -> + {builtin_u, Ann, chain_create, _Ar} -> case {ArgsT, Type} of {var_args, _} -> fcode_error({var_args_not_set, FunE}); {_, {con, _, Contract}} -> @@ -738,8 +738,8 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A builtin_to_fcode(state_layout(Env), chain_create, [{lit, {contract_code, Contract}}, {lit, FInitArgsT}|FArgs]); {_, _} -> fcode_error({not_a_contract_type, Type}) end; - {builtin_u, B, _Ar} -> builtin_to_fcode(state_layout(Env), B, FArgs); - {def_u, Ann, F, _Ar} -> {def, Ann, F, FArgs}; + {builtin_u, Ann, B, _Ar} -> builtin_to_fcode(state_layout(Env), B, FArgs); + {def_u, Ann, F, _Ar} -> {def, Ann, F, FArgs}; {remote_u, Ann, RArgsT, RRetT, Ct, RFun} -> {remote, Ann, RArgsT, RRetT, Ct, RFun, FArgs}; FFun -> %% FFun is a closure, with first component the function name and @@ -1265,8 +1265,8 @@ lambda_lift_expr(Layout, L = {lam, _, Xs, Body}) -> lambda_lift_expr(Layout, UExpr) when element(1, UExpr) == def_u; element(1, UExpr) == builtin_u -> [Tag, _, F, Ar | _] = tuple_to_list(UExpr), ExtraArgs = case UExpr of - {builtin_u, _, _, TypeArgs} -> TypeArgs; - _ -> [] + {builtin_u, _, _, _, TypeArgs} -> TypeArgs; + _ -> [] end, Xs = [ lists:concat(["arg", I]) || I <- lists:seq(1, Ar) ], Args = [{var, X} || X <- Xs] ++ ExtraArgs, @@ -1609,8 +1609,8 @@ read_only({get_state, _}) -> true; read_only({set_state, _, _, _}) -> false; read_only({def_u, _, _, _}) -> true; read_only({remote_u, _, _, _, _, _}) -> true; -read_only({builtin_u, _, _}) -> true; read_only({builtin_u, _, _, _}) -> true; +read_only({builtin_u, _, _, _, _}) -> true; read_only({lam, _, _, _}) -> true; read_only({def, _, _, _}) -> false; %% TODO: purity analysis read_only({remote, _, _, _, _, _, _}) -> false; @@ -1767,7 +1767,7 @@ resolve_fun(#{ fun_env := Funs, builtins := Builtin } = Env, Q) -> case {maps:get(Q, Funs, not_found), maps:get(Q, Builtin, not_found)} of {not_found, not_found} -> internal_error({unbound_variable, Q}); {_, {B, none}} -> builtin_to_fcode(state_layout(Env), B, []); - {_, {B, Ar}} -> {builtin_u, B, Ar}; + {_, {B, Ar}} -> {builtin_u, [], B, Ar}; {{Fun, Ar}, _} -> {def_u, [], Fun, Ar} end. @@ -1832,62 +1832,62 @@ free_vars(Xs) when is_list(Xs) -> lists:umerge([ free_vars(X) || X <- Xs ]); free_vars(Expr) -> case Expr of - {var, X} -> [X]; - {lit, _} -> []; - nil -> []; - {def, _, _, As} -> free_vars(As); - {def_u, _, _, _} -> []; + {var, X} -> [X]; + {lit, _} -> []; + nil -> []; + {def, _, _, As} -> free_vars(As); + {def_u, _, _, _} -> []; {remote, _, _, _, Ct, _, As} -> free_vars([Ct | As]); {remote_u, _, _, _, Ct, _} -> free_vars(Ct); - {builtin, _, As} -> free_vars(As); - {builtin_u, _, _} -> []; - {builtin_u, _, _, _} -> []; %% Typereps are always literals - {con, _, _, As} -> free_vars(As); - {tuple, As} -> free_vars(As); - {proj, _, A, _} -> free_vars(A); - {set_proj, _, A, _, B} -> free_vars([A, B]); - {op, _, _, As} -> free_vars(As); - {'let', Ann, X, A, B} -> free_vars([A, {lam, Ann, [X], B}]); - {funcall, _, A, Bs} -> free_vars([A | Bs]); - {set_state, _, _, A} -> free_vars(A); - {get_state, _} -> []; - {lam, _, Xs, B} -> free_vars(B) -- lists:sort(Xs); - {closure, _, _, A} -> free_vars(A); - {switch, A} -> free_vars(A); - {split, _, X, As} -> free_vars([{var, X} | As]); - {nosplit, A} -> free_vars(A); - {'case', P, A} -> free_vars(A) -- lists:sort(fsplit_pat_vars(P)) + {builtin, _, As} -> free_vars(As); + {builtin_u, _, _, _} -> []; + {builtin_u, _, _, _, _} -> []; %% Typereps are always literals + {con, _, _, As} -> free_vars(As); + {tuple, As} -> free_vars(As); + {proj, _, A, _} -> free_vars(A); + {set_proj, _, A, _, B} -> free_vars([A, B]); + {op, _, _, As} -> free_vars(As); + {'let', Ann, X, A, B} -> free_vars([A, {lam, Ann, [X], B}]); + {funcall, _, A, Bs} -> free_vars([A | Bs]); + {set_state, _, _, A} -> free_vars(A); + {get_state, _} -> []; + {lam, _, Xs, B} -> free_vars(B) -- lists:sort(Xs); + {closure, _, _, A} -> free_vars(A); + {switch, A} -> free_vars(A); + {split, _, X, As} -> free_vars([{var, X} | As]); + {nosplit, A} -> free_vars(A); + {'case', P, A} -> free_vars(A) -- lists:sort(fsplit_pat_vars(P)) end. used_defs(Xs) when is_list(Xs) -> lists:umerge([ used_defs(X) || X <- Xs ]); used_defs(Expr) -> case Expr of - {var, _} -> []; - {lit, _} -> []; - nil -> []; - {def, _, F, As} -> lists:umerge([F], used_defs(As)); - {def_u, _, F, _} -> [F]; + {var, _} -> []; + {lit, _} -> []; + nil -> []; + {def, _, F, As} -> lists:umerge([F], used_defs(As)); + {def_u, _, F, _} -> [F]; {remote, _, _, _, Ct, _, As} -> used_defs([Ct | As]); {remote_u, _, _, _, Ct, _} -> used_defs(Ct); - {builtin, _, As} -> used_defs(As); - {builtin_u, _, _} -> []; - {builtin_u, _, _, _} -> []; - {con, _, _, As} -> used_defs(As); - {tuple, As} -> used_defs(As); - {proj, _, A, _} -> used_defs(A); - {set_proj, _, A, _, B} -> used_defs([A, B]); - {op, _, _, As} -> used_defs(As); - {'let', _, _, A, B} -> used_defs([A, B]); - {funcall, _, A, Bs} -> used_defs([A | Bs]); - {set_state, _, _, A} -> used_defs(A); - {get_state, _} -> []; - {lam, _, _, B} -> used_defs(B); - {closure, _, F, A} -> lists:umerge([F], used_defs(A)); - {switch, A} -> used_defs(A); - {split, _, _, As} -> used_defs(As); - {nosplit, A} -> used_defs(A); - {'case', _, A} -> used_defs(A) + {builtin, _, As} -> used_defs(As); + {builtin_u, _, _, _} -> []; + {builtin_u, _, _, _, _} -> []; + {con, _, _, As} -> used_defs(As); + {tuple, As} -> used_defs(As); + {proj, _, A, _} -> used_defs(A); + {set_proj, _, A, _, B} -> used_defs([A, B]); + {op, _, _, As} -> used_defs(As); + {'let', _, _, A, B} -> used_defs([A, B]); + {funcall, _, A, Bs} -> used_defs([A | Bs]); + {set_state, _, _, A} -> used_defs(A); + {get_state, _} -> []; + {lam, _, _, B} -> used_defs(B); + {closure, _, F, A} -> lists:umerge([F], used_defs(A)); + {switch, A} -> used_defs(A); + {split, _, _, As} -> used_defs(As); + {nosplit, A} -> used_defs(A); + {'case', _, A} -> used_defs(A) end. bottom_up(F, Expr) -> bottom_up(F, #{}, Expr). @@ -1900,8 +1900,8 @@ bottom_up(F, Env, Expr) -> {def, Ann, D, Es} -> {def, Ann, D, [bottom_up(F, Env, E) || E <- Es]}; {def_u, _, _, _} -> Expr; {builtin, B, Es} -> {builtin, B, [bottom_up(F, Env, E) || E <- Es]}; - {builtin_u, _, _} -> Expr; {builtin_u, _, _, _} -> Expr; + {builtin_u, _, _, _, _} -> Expr; {remote, Ann, ArgsT, RetT, Ct, Fun, Es} -> {remote, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun, [bottom_up(F, Env, E) || E <- Es]}; {remote_u, Ann, ArgsT, RetT, Ct, Fun} -> {remote_u, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun}; {con, Ar, I, Es} -> {con, Ar, I, [bottom_up(F, Env, E) || E <- Es]}; @@ -1958,8 +1958,8 @@ rename(Ren, Expr) -> {def, Ann, D, Es} -> {def, Ann, D, [rename(Ren, E) || E <- Es]}; {def_u, _, _, _} -> Expr; {builtin, B, Es} -> {builtin, B, [rename(Ren, E) || E <- Es]}; - {builtin_u, _, _} -> Expr; {builtin_u, _, _, _} -> Expr; + {builtin_u, _, _, _, _} -> Expr; {remote, Ann, ArgsT, RetT, Ct, F, Es} -> {remote, Ann, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; {remote_u, Ann, ArgsT, RetT, Ct, F} -> {remote_u, Ann, ArgsT, RetT, rename(Ren, Ct), F}; {con, Ar, I, Es} -> {con, Ar, I, [rename(Ren, E) || E <- Es]}; @@ -2203,9 +2203,9 @@ pp_fexpr({'let', _, _, _, _} = Expr) -> pp_above([ pp_par([pp_text(X), pp_text("="), prettypr:nest(2, pp_fexpr(A))]) || {X, A} <- Ls ]), pp_text(" in ") ]), pp_fexpr(Body) ])); -pp_fexpr({builtin_u, B, N}) -> +pp_fexpr({builtin_u, _, B, N}) -> pp_beside([pp_text(B), pp_text("/"), pp_text(N)]); -pp_fexpr({builtin_u, B, N, TypeArgs}) -> +pp_fexpr({builtin_u, _, B, N, TypeArgs}) -> pp_beside([pp_text(B), pp_text("@"), pp_fexpr({tuple, TypeArgs}), pp_text("/"), pp_text(N)]); pp_fexpr({builtin, B, As}) -> pp_call(pp_text(B), As); -- 2.30.2 From 81fc1de4793d80a9701fd2b1a9fe4eb820797693 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Mon, 7 Nov 2022 15:35:08 +0300 Subject: [PATCH 14/92] Add missing functions specs --- src/aeso_ast_to_fcode.erl | 179 ++++++++++++++++++++++++++++++++++---- 1 file changed, 164 insertions(+), 15 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index e5b989b..8960c2a 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -117,18 +117,21 @@ | bits | {variant, [[ftype()]]} | {function, [ftype()], ftype()} - | any | {tvar, var_name()}. + | any + | {tvar, var_name()}. -type fun_def() :: #{ attrs := [attribute()], args := [{var_name(), ftype()}], return := ftype(), body := fexpr() }. +-type functions() :: #{ fun_name() => fun_def() }. + -type fcode() :: #{ contract_name := string(), state_type := ftype(), state_layout := state_layout(), event_type := ftype() | none, - functions := #{ fun_name() => fun_def() }, + functions := functions(), payable := boolean() }. -type type_def() :: fun(([ftype()]) -> ftype()). @@ -139,11 +142,14 @@ -record(con_tag, { tag :: tag(), arities :: arities() }). -type con_tag() :: #con_tag{}. --type type_env() :: #{ sophia_name() => type_def() }. --type fun_env() :: #{ sophia_name() => {fun_name(), non_neg_integer()} }. --type con_env() :: #{ sophia_name() => con_tag() }. --type child_con_env() :: #{sophia_name() => fcode()}. --type builtins() :: #{ sophia_name() => {builtin(), non_neg_integer() | none | variable} }. +-type expr_env() :: #{ var_name() => fexpr() }. +-type type_env() :: #{ sophia_name() => type_def() }. +-type fun_env() :: #{ sophia_name() => {fun_name(), non_neg_integer()} }. +-type con_env() :: #{ sophia_name() => con_tag() }. +-type child_con_env() :: #{ sophia_name() => fcode() }. +-type builtins() :: #{ sophia_name() => {builtin(), non_neg_integer() | none | variable} }. + +-type rename() :: [{var_name(), var_name()}]. -type context() :: {contract_def, string()} | {namespace, string()} @@ -190,6 +196,7 @@ ast_to_fcode(Code, Options) -> clear_fresh_names(Options), {Env3, FCode2}. +-spec optimize(fcode(), [option()]) -> fcode(). optimize(FCode1, Options) -> Verbose = lists:member(pp_fcode, Options), [io:format("-- Before lambda lifting --\n~s\n\n", [format_fcode(FCode1)]) || Verbose], @@ -288,6 +295,7 @@ builtins() -> || {NS, Funs} <- Scopes, {Fun, Arity} <- Funs ]). +-spec state_layout(env()) -> state_layout(). state_layout(Env) -> maps:get(state_layout, Env, {reg, 1}). -define(type(T), fun([]) -> T end). @@ -324,12 +332,15 @@ init_type_env() -> ["MCL_BLS12_381", "fp"] => ?type({bytes, 48}) }. +-spec is_no_code(env()) -> boolean(). is_no_code(Env) -> get_option(no_code, Env). +-spec get_option(atom(), env()) -> option(). get_option(Opt, Env) -> get_option(Opt, Env, false). +-spec get_option(atom(), env(), option()) -> option(). get_option(Opt, Env, Default) -> proplists:get_value(Opt, maps:get(options, Env, []), Default). @@ -451,6 +462,7 @@ typedef_to_fcode(Env, {id, _, Name}, Xs, Def) -> Env3 = compute_state_layout(Env2, Name, FDef), bind_type(Env3, Q, FDef). +-spec compute_state_layout(env(), string(), type_def()) -> env(). compute_state_layout(Env = #{ context := {contract_def, _} }, "state", Type) -> NoLayout = get_option(no_flatten_state, Env), Layout = @@ -463,6 +475,7 @@ compute_state_layout(Env = #{ context := {contract_def, _} }, "state", Type) -> Env#{ state_layout => Layout }; compute_state_layout(Env, _, _) -> Env. +-spec compute_state_layout(state_reg(), ftype()) -> {state_reg(), state_layout() | [state_layout()]}. compute_state_layout(R, {tuple, [T]}) -> compute_state_layout(R, T); compute_state_layout(R, {tuple, Ts}) -> @@ -517,6 +530,7 @@ args_to_fcode(Env, Args) -> -define(make_let(X, Expr, Body), make_let(Expr, fun(X) -> Body end)). +-spec make_let(fexpr(), fun((fexpr()) -> fexpr())) -> fexpr(). make_let(Expr, Body) -> case Expr of {var, _} -> Body(Expr); @@ -527,9 +541,11 @@ make_let(Expr, Body) -> {'let', get_fann(Expr), X, Expr, Body({var, X})} end. +-spec let_bind(var_name(), fexpr(), fexpr()) -> fexpr(). let_bind(X, {var, Y}, Body) -> rename([{X, Y}], Body); let_bind(X, Expr, Body) -> {'let', get_fann(Expr), X, Expr, Body}. +-spec let_bind([{var_name(), fexpr()}], fexpr()) -> fexpr(). let_bind(Binds, Body) -> lists:foldr(fun({X, E}, Rest) -> let_bind(X, E, Rest) end, Body, Binds). @@ -606,7 +622,7 @@ expr_to_fcode(Env, Type, {proj, Ann, Rec = {typed, _, _, RecType}, {id, _, X}}) {entrypoint, list_to_binary(X)}}; {record_t, [_]} -> expr_to_fcode(Env, Rec); %% Singleton record {record_t, _} -> - {proj, to_fann(Ann), expr_to_fcode(Env, Rec), field_index(Rec, X)} + {proj, to_fann(Ann), expr_to_fcode(Env, Rec), field_index(RecType, X)} end; expr_to_fcode(Env, {record_t, [FieldT]}, {record, _Ann, [_] = Fields}) -> @@ -796,6 +812,7 @@ expr_to_fcode(Env, _Type, {lam, Ann, Args, Body}) -> expr_to_fcode(_Env, Type, Expr) -> error({todo, {Expr, ':', Type}}). +-spec make_if(fexpr(), fexpr(), fexpr()) -> fexpr(). make_if({var, X}, Then, Else) -> {switch, {split, boolean, X, [{'case', {bool, false}, {nosplit, Else}}, @@ -804,6 +821,7 @@ make_if(Cond, Then, Else) -> X = fresh_name(), {'let', get_fann(Cond), X, Cond, make_if({var, X}, Then, Else)}. +-spec make_if_no_else(fexpr(), fexpr()) -> fexpr(). make_if_no_else({var, X}, Then) -> {switch, {split, boolean, X, [{'case', {bool, true}, {nosplit, Then}}]}}; @@ -819,6 +837,10 @@ make_tuple(Es) -> {tuple, Es}. strip_singleton_tuples({tuple, [T]}) -> strip_singleton_tuples(T); strip_singleton_tuples(T) -> T. +-spec get_oracle_type(OracleFun, FunT) -> OracleType when + OracleFun :: atom(), + FunT :: aeso_syntax:type(), + OracleType :: aeso_syntax:type(). get_oracle_type(oracle_register, {fun_t, _, _, _, OType}) -> OType; get_oracle_type(oracle_query, {fun_t, _, _, [OType | _], _}) -> OType; get_oracle_type(oracle_get_question, {fun_t, _, _, [OType | _], _}) -> OType; @@ -840,11 +862,13 @@ alts_to_fcode(Env, Type, X, Alts, Switch) -> | {bool, false | true} | {int, integer()} | {string, binary()} - | nil | {'::', fpat(), fpat()} + | nil + | {'::', fpat(), fpat()} | {tuple, [fpat()]} | {con, arities(), tag(), [fpat()]} | {assign, fpat(), fpat()}. +-spec remove_guards(env(), [aeso_syntax:alt()], aeso_syntax:expr()) -> [falt()]. remove_guards(_Env, [], _Switch) -> []; remove_guards(Env, [Alt = {'case', _, _, [{guarded, _, [], _Expr}]} | Rest], Switch) -> @@ -903,10 +927,13 @@ split_tree(Env, Vars, Alts = [{'case', Pats, Body} | _]) -> {split, Type1, X, Cases} end. --spec merge_alts(integer(), var_name(), [{fsplit_pat(), falt()}]) -> [{fsplit_pat(), [falt()]}]. +-spec merge_alts(integer(), var_name(), Alts) -> [{fsplit_pat(), [falt()]}] when + Alts :: [{fsplit_pat(), falt()}]. merge_alts(I, X, Alts) -> merge_alts(I, X, Alts, []). +-spec merge_alts(integer(), var_name(), Alts, Alts) -> [{fsplit_pat(), [falt()]}] when + Alts :: [{fsplit_pat(), falt()}]. merge_alts(I, X, Alts, Alts1) -> lists:foldr(fun(A, As) -> merge_alt(I, X, A, As) end, Alts1, Alts). @@ -937,6 +964,7 @@ merge_alt(I, X, {P, A}, [{Q, As} | Rest]) -> insert -> [{P, [A]}, {Q, As} | Rest] end. +-spec expand(integer(), var_name(), fsplit_pat(), fsplit_pat(), falt()) -> term(). expand(I, X, P, Q, Case = {'case', Ps, E}) -> {Ps0, [{var, Y} | Ps1]} = lists:split(I - 1, Ps), {Ps0r, Ren1} = rename_fpats([{Y, X} || Y /= X], Ps0), @@ -1054,6 +1082,12 @@ pat_to_fcode(_Env, Type, Pat) -> %% -- Decision trees for boolean operators -- +-type decision_tree() :: false + | true + | {atom, fexpr()} + | {'if', fexpr(), decision_tree(), decision_tree()}. + +-spec decision_op(aeso_syntax:op(), decision_tree(), decision_tree()) -> decision_tree(). decision_op('&&', {atom, A}, B) -> {'if', A, B, false}; decision_op('&&', false, _) -> false; decision_op('&&', true, B) -> B; @@ -1063,12 +1097,14 @@ decision_op('||', true, _) -> true; decision_op(Op, {'if', A, Then, Else}, B) -> {'if', A, decision_op(Op, Then, B), decision_op(Op, Else, B)}. +-spec expr_to_decision_tree(env(), aeso_syntax:expr()) -> decision_tree(). expr_to_decision_tree(Env, {app, _Ann, {Op, _}, [A, B]}) when Op == '&&'; Op == '||' -> decision_op(Op, expr_to_decision_tree(Env, A), expr_to_decision_tree(Env, B)); expr_to_decision_tree(Env, {typed, _, Expr, _}) -> expr_to_decision_tree(Env, Expr); expr_to_decision_tree(Env, Expr) -> {atom, expr_to_fcode(Env, Expr)}. +-spec decision_tree_to_fcode(decision_tree()) -> fexpr(). decision_tree_to_fcode(false) -> {lit, {bool, false}}; decision_tree_to_fcode(true) -> {lit, {bool, true}}; decision_tree_to_fcode({atom, B}) -> B; @@ -1099,6 +1135,8 @@ stmts_to_fcode(Env, [Expr | Stmts]) -> %% -- Builtins -- +-spec op_builtins() -> [BuiltinFun] when + BuiltinFun :: atom(). op_builtins() -> [map_from_list, map_to_list, map_delete, map_member, map_size, stringinternal_length, stringinternal_concat, stringinternal_to_list, stringinternal_from_list, @@ -1118,6 +1156,7 @@ op_builtins() -> mcl_bls12_381_int_to_fr, mcl_bls12_381_int_to_fp, mcl_bls12_381_fr_to_int, mcl_bls12_381_fp_to_int ]. +-spec set_state(state_layout(), fexpr()) -> fexpr(). set_state({reg, R}, Val) -> {set_state, get_fann(Val), R, Val}; set_state({tuple, Ls}, Val) -> @@ -1126,11 +1165,14 @@ set_state({tuple, Ls}, Val) -> {'let', [], "_", set_state(L, {proj, get_fann(Val), X, I - 1}), Code} end, {tuple, []}, indexed(Ls))). +-spec get_state(state_layout()) -> fexpr(). get_state({reg, R}) -> {get_state, R}; get_state({tuple, Ls}) -> {tuple, [get_state(L) || L <- Ls]}. +-spec builtin_to_fcode(state_layout(), BuiltinFun, [fexpr()]) -> fexpr() when + BuiltinFun :: atom(). %% No need to mention all of them builtin_to_fcode(Layout, set_state, [Val]) -> set_state(Layout, Val); builtin_to_fcode(Layout, get_state, []) -> @@ -1163,6 +1205,7 @@ builtin_to_fcode(_Layout, Builtin, Args) -> %% -- Init function -- +-spec add_init_function(env(), functions()) -> functions(). add_init_function(Env, Funs0) -> case is_no_code(Env) of true -> Funs0; @@ -1175,6 +1218,7 @@ add_init_function(Env, Funs0) -> Funs1 end. +-spec add_default_init_function(env(), functions()) -> functions(). add_default_init_function(_Env, Funs) -> InitName = {entrypoint, <<"init">>}, case maps:get(InitName, Funs, none) of @@ -1188,10 +1232,12 @@ add_default_init_function(_Env, Funs) -> %% -- Event function -- +-spec add_event_function(env(), ftype() | none, functions()) -> functions(). add_event_function(_Env, none, Funs) -> Funs; add_event_function(Env, EventFType, Funs) -> Funs#{ event => event_function(Env, EventFType) }. +-spec event_function(env(), ftype()) -> fun_def(). event_function(_Env = #{event_type := {variant_t, EventCons}}, EventType = {variant, FCons}) -> Cons = [ {Name, I - 1, proplists:get_value(indices, Ann)} || {I, {constr_t, Ann, {con, _, Name}, _}} <- indexed(EventCons) ], @@ -1228,18 +1274,25 @@ lambda_lift(FCode = #{ functions := Funs, state_layout := StateLayout }) -> FCode#{ functions := maps:merge(Funs1, NewFuns) }. -define(lambda_key, '%lambdalifted'). + +-spec init_lambda_funs() -> term(). init_lambda_funs() -> put(?lambda_key, #{}). + +-spec get_lambda_funs() -> term(). get_lambda_funs() -> erase(?lambda_key). +-spec add_lambda_fun(fun_def()) -> fun_name(). add_lambda_fun(Def) -> Name = fresh_fun(), Funs = get(?lambda_key), put(?lambda_key, Funs#{ Name => Def }), Name. +-spec lambda_lift_fun(state_layout(), fun_def()) -> fun_def(). lambda_lift_fun(Layout, Def = #{ body := Body }) -> Def#{ body := lambda_lift_expr(Layout, Body) }. +-spec lifted_fun([var_name()], [var_name()], fexpr()) -> fun_def(). lifted_fun([Z], Xs, Body) -> #{ attrs => [private], args => [{Z, any} | [{X, any} || X <- Xs]], @@ -1254,11 +1307,15 @@ lifted_fun(FVs, Xs, Body) -> body => lists:foldr(Proj, Body, indexed(FVs)) }. +-spec make_closure([var_name()], [var_name()], fexpr()) -> Closure when + Closure :: fexpr(). make_closure(FVs, Xs, Body) -> Fun = add_lambda_fun(lifted_fun(FVs, Xs, Body)), Tup = fun([Y]) -> Y; (Ys) -> {tuple, Ys} end, {closure, get_fann(Body), Fun, Tup([{var, Y} || Y <- FVs])}. +-spec lambda_lift_expr(state_layout(), fexpr()) -> Closure when + Closure :: fexpr(). lambda_lift_expr(Layout, L = {lam, _, Xs, Body}) -> FVs = free_vars(L), make_closure(FVs, Xs, lambda_lift_expr(Layout, Body)); @@ -1306,6 +1363,8 @@ lambda_lift_expr(Layout, Expr) -> {'case', P, S} -> {'case', P, lambda_lift_expr(Layout, S)} end. +-spec lambda_lift_exprs(state_layout(), [fexpr()]) -> [Closure] when + Closure :: fexpr(). lambda_lift_exprs(Layout, As) -> [lambda_lift_expr(Layout, A) || A <- As]. %% -- Optimisations ---------------------------------------------------------- @@ -1349,25 +1408,33 @@ inliner(Fcode, Fun, {def, _, Fun1, Args} = E) when Fun1 /= Fun -> end; inliner(_Fcode, _Fun, E) -> E. +-spec should_inline(fcode(), fun_name()) -> boolean(). should_inline(_Fcode, _Fun1) -> false == list_to_atom("true"). %% Dialyzer +-spec inline(fcode(), fun_name(), Args) -> Def when + Args :: [fexpr()], + Def :: fexpr(). inline(_Fcode, Fun, Args) -> {def, [], Fun, Args}. %% TODO %% --- Bind subexpressions --- -define(make_lets(Xs, Es, Body), make_lets(Es, fun(Xs) -> Body end)). +-spec bind_subexpressions(fexpr()) -> fexpr(). bind_subexpressions(Expr) -> bottom_up(fun bind_subexpressions/2, Expr). +-spec bind_subexpressions(expr_env(), fexpr()) -> fexpr(). bind_subexpressions(_, {tuple, Es}) -> ?make_lets(Xs, Es, {tuple, Xs}); bind_subexpressions(_, {set_proj, Ann, A, I, B}) -> ?make_lets([X, Y], [A, B], {set_proj, Ann, X, I, Y}); bind_subexpressions(_, E) -> E. +-spec make_lets([fexpr()], fun(([fexpr()]) -> fexpr())) -> fexpr(). make_lets(Es, Body) -> make_lets(Es, [], Body). +-spec make_lets([fexpr()], [fexpr()], fun(([fexpr()]) -> fexpr())) -> fexpr(). make_lets([], Xs, Body) -> Body(lists:reverse(Xs)); make_lets([{var, _} = E | Es], Xs, Body) -> make_lets(Es, [E | Xs], Body); @@ -1378,9 +1445,11 @@ make_lets([E | Es], Xs, Body) -> %% --- Inline local functions --- +-spec inline_local_functions(fexpr()) -> fexpr(). inline_local_functions(Expr) -> bottom_up(fun inline_local_functions/2, Expr). +-spec inline_local_functions(expr_env(), fexpr()) -> fexpr(). inline_local_functions(Env, {funcall, _, {proj, _, {var, Y}, 0}, [{proj, _, {var, Y}, 1} | Args]} = Expr) -> %% TODO: Don't always inline local funs? case maps:get(Y, Env, free) of @@ -1391,8 +1460,10 @@ inline_local_functions(_, Expr) -> Expr. %% --- Let-floating --- +-spec let_floating(fexpr()) -> fexpr(). let_floating(Expr) -> bottom_up(fun let_float/2, Expr). +-spec let_float(expr_env(), fexpr()) -> fexpr(). let_float(_, {'let', Ann, X, E, Body}) -> pull_out_let({'let', Ann, X, {here, E}, Body}); let_float(_, {proj, Ann, E, I}) -> @@ -1404,6 +1475,8 @@ let_float(_, {op, Ann, Op, Es}) -> let_bind(Lets, {op, Ann, Op, Es1}); let_float(_, E) -> E. +-spec pull_out_let(fexpr() | [fexpr()]) -> fexpr() | {Lets, [fexpr()]} when + Lets :: [{var_name(), fexpr()}]. pull_out_let(Expr) when is_tuple(Expr) -> {Lets, Es} = pull_out_let(tuple_to_list(Expr)), Inner = list_to_tuple(Es), @@ -1423,8 +1496,12 @@ pull_out_let(Es) when is_list(Es) -> end. %% Also renames the variables to fresh names +-spec let_view(fexpr()) -> {Lets, fexpr()} when + Lets :: [{var_name(), fexpr()}]. let_view(E) -> let_view(E, [], []). +-spec let_view(fexpr(), rename(), Lets) -> {Lets, fexpr()} when + Lets :: [{var_name(), fexpr()}]. let_view({'let', _, X, E, Rest}, Ren, Lets) -> Z = fresh_name(), let_view(Rest, [{X, Z} | Ren], [{Z, rename(Ren, E)} | Lets]); @@ -1437,7 +1514,7 @@ let_view(E, Ren, Lets) -> simplifier(Expr) -> bottom_up(fun simplify/2, Expr). --spec simplify(#{var_name() => fexpr()}, fexpr()) -> fexpr(). +-spec simplify(expr_env(), fexpr()) -> fexpr(). %% (e₀, .., en).i -> %% let _ = e₀ in .. let x = ei in .. let _ = en in x @@ -1476,6 +1553,7 @@ simplify(Env, {switch, Split}) -> simplify(_, E) -> E. +-spec simpl_proj(expr_env(), integer(), fexpr()) -> fexpr() | false. simpl_proj(Env, I, Expr) -> IfSafe = fun(E) -> case safe_to_duplicate(E) of true -> E; @@ -1491,6 +1569,7 @@ simpl_proj(Env, I, Expr) -> _ -> false end. +-spec get_catchalls([fcase()]) -> [fcase()]. get_catchalls(Alts) -> [ C || C = {'case', {var, _}, _} <- Alts ]. @@ -1502,6 +1581,7 @@ get_catchalls(Alts) -> %% _ => switch(x) %% .. %% _ => e +-spec add_catchalls([fcase()], [fcase()]) -> [fcase()]. add_catchalls(Alts, []) -> Alts; add_catchalls(Alts, Catchalls) -> case lists:splitwith(fun({'case', {var, _}, _}) -> false; (_) -> true end, @@ -1511,10 +1591,12 @@ add_catchalls(Alts, Catchalls) -> %% NOTE: relies on catchalls always being at the end end. +-spec nest_catchalls([fcase()]) -> fcase(). nest_catchalls([C = {'case', {var, _}, {nosplit, _}} | _]) -> C; nest_catchalls([{'case', P = {var, _}, {split, Type, X, Alts}} | Catchalls]) -> {'case', P, {split, Type, X, add_catchalls(Alts, Catchalls)}}. +-spec simpl_switch(expr_env(), [fcase()], fsplit()) -> fexpr() | stuck | nomatch. simpl_switch(_Env, _, {nosplit, E}) -> E; simpl_switch(Env, Catchalls, {split, Type, X, Alts}) -> Alts1 = add_catchalls(Alts, Catchalls), @@ -1528,6 +1610,7 @@ simpl_switch(Env, Catchalls, {split, Type, X, Alts}) -> end end. +-spec simpl_case(expr_env(), fexpr(), [fcase()]) -> fexpr() | stuck | nomatch. simpl_case(_, _, []) -> nomatch; simpl_case(Env, E, [{'case', Pat, Body} | Alts]) -> case match_pat(Pat, E) of @@ -1551,6 +1634,7 @@ match_pat({var, X}, E) -> [{X, E}]; match_pat({assign, X, P}, E) -> [{X, E}, {P, E}]; match_pat(_, _) -> false. +-spec constructor_form(expr_env(), fexpr()) -> fexpr() | false. constructor_form(Env, Expr) -> case Expr of {var, X} -> @@ -1578,8 +1662,10 @@ constructor_form(Env, Expr) -> %% --- Drop unused lets --- +-spec drop_unused_lets(fexpr()) -> fexpr(). drop_unused_lets(Expr) -> bottom_up(fun drop_unused_lets/2, Expr). +-spec drop_unused_lets(expr_env(), fexpr()) -> fexpr(). drop_unused_lets(_, {'let', Ann, X, E, Body} = Expr) -> case {read_only(E), not lists:member(X, free_vars(Body))} of {true, true} -> Body; @@ -1590,6 +1676,7 @@ drop_unused_lets(_, Expr) -> Expr. %% -- Static analysis -------------------------------------------------------- +-spec safe_to_duplicate(fexpr()) -> boolean(). safe_to_duplicate({lit, _}) -> true; safe_to_duplicate({var, _}) -> true; safe_to_duplicate(nil) -> true; @@ -1632,12 +1719,15 @@ eliminate_dead_code(Code = #{ functions := Funs }) -> Code#{ functions := maps:filter(fun(Name, _) -> maps:is_key(Name, UsedFuns) end, Funs) }. --spec used_functions(#{ fun_name() => fun_def() }) -> #{ fun_name() => true }. +-spec used_functions(functions()) -> Used when + Used :: #{ fun_name() => true }. used_functions(Funs) -> Exported = [ Fun || {Fun, #{ attrs := Attrs }} <- maps:to_list(Funs), not lists:member(private, Attrs) ], used_functions(#{}, Exported, Funs). +-spec used_functions(Used, [fun_name()], functions()) -> Used when + Used :: #{ fun_name() => true }. used_functions(Used, [], _) -> Used; used_functions(Used, [Name | Rest], Defs) -> case maps:is_key(Name, Used) of @@ -1698,6 +1788,7 @@ add_fun_env(Env = #{ fun_env := FunEnv }, Decls) -> FunEnv1 = maps:from_list(lists:flatmap(Entry, Decls)), Env#{ fun_env := maps:merge(FunEnv, FunEnv1) }. +-spec make_fun_name(env(), aeso_syntax:ann(), aeso_syntax:name()) -> fun_name(). make_fun_name(#{ context := Context }, Ann, Name) -> Entrypoint = proplists:get_value(entrypoint, Ann, false), case Context of @@ -1737,11 +1828,14 @@ lookup_con(#{ con_env := ConEnv }, Con) -> Tag -> Tag end. +-spec bind_vars(env(), [var_name()]) -> env(). bind_vars(Env, Xs) -> lists:foldl(fun(X, E) -> bind_var(E, X) end, Env, Xs). +-spec bind_var(env(), var_name()) -> env(). bind_var(Env = #{ vars := Vars }, X) -> Env#{ vars := [X | Vars] }. +-spec resolve_var(env(), [aeso_syntax:name()]) -> fexpr(). resolve_var(#{ vars := Vars } = Env, [X]) -> case lists:member(X, Vars) of true -> {var, X}; @@ -1763,6 +1857,7 @@ resolve_const(#{ consts := Consts }, Q) -> Val -> Val end. +-spec resolve_fun(env(), [aeso_syntax:name()]) -> fexpr(). resolve_fun(#{ fun_env := Funs, builtins := Builtin } = Env, Q) -> case {maps:get(Q, Funs, not_found), maps:get(Q, Builtin, not_found)} of {not_found, not_found} -> internal_error({unbound_variable, Q}); @@ -1771,17 +1866,21 @@ resolve_fun(#{ fun_env := Funs, builtins := Builtin } = Env, Q) -> {{Fun, Ar}, _} -> {def_u, [], Fun, Ar} end. +-spec init_fresh_names([option()]) -> term(). init_fresh_names(Options) -> proplists:get_value(debug_info, Options, false) andalso init_saved_fresh_names(), put('%fresh', 0). +-spec clear_fresh_names([option()]) -> term(). clear_fresh_names(Options) -> proplists:get_value(debug_info, Options, false) andalso clear_saved_fresh_names(), erase('%fresh'). +-spec init_saved_fresh_names() -> term(). init_saved_fresh_names() -> put(saved_fresh_names, #{}). +-spec clear_saved_fresh_names() -> term(). clear_saved_fresh_names() -> erase(saved_fresh_names). @@ -1828,6 +1927,7 @@ fsplit_pat_vars({'::', P, Q}) -> [P, Q]; fsplit_pat_vars({tuple, Ps}) -> Ps; fsplit_pat_vars({con, _, _, Ps}) -> Ps. +-spec free_vars(fexpr() | [fexpr()]) -> [var_name()]. free_vars(Xs) when is_list(Xs) -> lists:umerge([ free_vars(X) || X <- Xs ]); free_vars(Expr) -> @@ -1859,6 +1959,7 @@ free_vars(Expr) -> {'case', P, A} -> free_vars(A) -- lists:sort(fsplit_pat_vars(P)) end. +-spec used_defs(fexpr() | [fexpr()]) -> [fun_name()]. used_defs(Xs) when is_list(Xs) -> lists:umerge([ used_defs(X) || X <- Xs ]); used_defs(Expr) -> @@ -1890,8 +1991,12 @@ used_defs(Expr) -> {'case', _, A} -> used_defs(A) end. +-spec bottom_up(Fun, fexpr()) -> fexpr() when + Fun :: fun((expr_env(), fexpr()) -> fexpr()). bottom_up(F, Expr) -> bottom_up(F, #{}, Expr). +-spec bottom_up(Fun, expr_env(), fexpr()) -> fexpr() when + Fun :: fun((expr_env(), fexpr()) -> fexpr()). bottom_up(F, Env, Expr) -> F(Env, case Expr of {lit, _} -> Expr; @@ -1934,6 +2039,7 @@ bottom_up(F, Env, Expr) -> {'case', Pat, Split} -> {'case', Pat, bottom_up(F, Env, Split)} end). +-spec get_named_args([aeso_syntax:named_arg_t()], [aeso_syntax:arg_expr()]) -> [aeso_syntax:expr()]. get_named_args(NamedArgsT, Args) -> IsNamed = fun({named_arg, _, _, _}) -> true; (_) -> false end, @@ -1941,6 +2047,7 @@ get_named_args(NamedArgsT, Args) -> NamedArgs = [get_named_arg(NamedArg, Named) || NamedArg <- NamedArgsT], NamedArgs ++ NotNamed. +-spec get_named_arg(aeso_syntax:named_arg_t(), [aeso_syntax:arg_expr()]) -> aeso_syntax:expr(). get_named_arg({named_arg_t, _, {id, _, Name}, _, Default}, Args) -> case [ Val || {named_arg, _, {id, _, X}, Val} <- Args, X == Name ] of [Val] -> Val; @@ -1949,7 +2056,7 @@ get_named_arg({named_arg_t, _, {id, _, Name}, _, Default}, Args) -> %% -- Renaming -- --spec rename([{var_name(), var_name()}], fexpr()) -> fexpr(). +-spec rename(rename(), fexpr()) -> fexpr(). rename(Ren, Expr) -> case Expr of {lit, _} -> Expr; @@ -1980,7 +2087,10 @@ rename(Ren, Expr) -> {'let', Ann, Z, rename(Ren, E), rename(Ren1, Body)} end. +-spec rename_var(rename(), var_name()) -> var_name(). rename_var(Ren, X) -> proplists:get_value(X, Ren, X). + +-spec rename_binding(rename(), var_name()) -> {var_name(), rename()}. rename_binding(Ren, X) -> Ren1 = lists:keydelete(X, 1, Ren), case lists:keymember(X, 2, Ren) of @@ -1990,18 +2100,21 @@ rename_binding(Ren, X) -> {Z, [{X, Z} | Ren1]} end. +-spec rename_bindings(rename(), [var_name()]) -> {[var_name()], rename()}. rename_bindings(Ren, []) -> {[], Ren}; rename_bindings(Ren, [X | Xs]) -> {Z, Ren1} = rename_binding(Ren, X), {Zs, Ren2} = rename_bindings(Ren1, Xs), {[Z | Zs], Ren2}. +-spec rename_fpats(rename(), [fpat()]) -> {[fpat()], rename()}. rename_fpats(Ren, []) -> {[], Ren}; rename_fpats(Ren, [P | Ps]) -> {Q, Ren1} = rename_fpat(Ren, P), {Qs, Ren2} = rename_fpats(Ren1, Ps), {[Q | Qs], Ren2}. +-spec rename_fpat(rename(), fpat()) -> {fpat(), rename()}. rename_fpat(Ren, P = {bool, _}) -> {P, Ren}; rename_fpat(Ren, P = {int, _}) -> {P, Ren}; rename_fpat(Ren, P = {string, _}) -> {P, Ren}; @@ -2020,6 +2133,7 @@ rename_fpat(Ren, {tuple, Ps}) -> {Ps1, Ren1} = rename_fpats(Ren, Ps), {{tuple, Ps1}, Ren1}. +-spec rename_spat(rename(), fsplit_pat()) -> {fsplit_pat(), rename()}. rename_spat(Ren, P = {bool, _}) -> {P, Ren}; rename_spat(Ren, P = {int, _}) -> {P, Ren}; rename_spat(Ren, P = {string, _}) -> {P, Ren}; @@ -2042,23 +2156,27 @@ rename_spat(Ren, {assign, X, P}) -> {P1, Ren2} = rename_binding(Ren1, P), {{assign, X1, P1}, Ren2}. +-spec rename_split(rename(), fsplit()) -> fsplit(). rename_split(Ren, {split, Type, X, Cases}) -> {split, Type, rename_var(Ren, X), [rename_case(Ren, C) || C <- Cases]}; rename_split(Ren, {nosplit, E}) -> {nosplit, rename(Ren, E)}. +-spec rename_case(rename(), fcase()) -> fcase(). rename_case(Ren, {'case', Pat, Split}) -> {Pat1, Ren1} = rename_spat(Ren, Pat), {'case', Pat1, rename_split(Ren1, Split)}. %% -- Records -- -field_index({typed, _, _, RecTy}, X) -> - field_index(RecTy, X); +-spec field_index(aeso_syntax:typedef(), aeso_syntax:name()) -> integer(). field_index({record_t, Fields}, X) -> IsX = fun({field_t, _, {id, _, Y}, _}) -> X == Y end, [I] = [ I || {I, Field} <- indexed(Fields), IsX(Field) ], I - 1. %% Tuples are 0-indexed +-spec field_value(aeso_syntax:field_t(), [aeso_syntax:field(aeso_syntax:pat())]) -> Res when + Res :: {upd, aeso_syntax:name(), Expr} | {set, Expr} | false, + Expr :: aeso_syntax:expr(). field_value({field_t, _, {id, _, X}, _}, Fields) -> View = fun({field, _, [{proj, _, {id, _, Y}}], E}) -> {Y, {set, E}}; ({field_upd, _, [{proj, _, {id, _, Y}}], @@ -2070,6 +2188,7 @@ field_value({field_t, _, {id, _, X}, _}, Fields) -> %% -- Attributes -- +-spec get_attributes(aeso_syntax:ann()) -> [stateful | payable | private]. get_attributes(Ann) -> [stateful || proplists:get_value(stateful, Ann, false)] ++ [payable || proplists:get_value(payable, Ann, false)] ++ @@ -2077,36 +2196,46 @@ get_attributes(Ann) -> %% -- Basic utilities -- +-spec indexed([term()]) -> [{integer(), term()}]. indexed(Xs) -> lists:zip(lists:seq(1, length(Xs)), Xs). +-spec setnth(integer(), Val, Vals) -> Vals when + Val :: term(), + Vals :: [Val]. setnth(I, X, Xs) -> {Ys, [_ | Zs]} = lists:split(I - 1, Xs), Ys ++ [X] ++ Zs. -dialyzer({nowarn_function, [fcode_error/1, internal_error/1]}). +-spec fcode_error(string()) -> no_return(). fcode_error(Error) -> Pos = aeso_errors:pos(0, 0), Msg = lists:flatten(io_lib:format("Unknown error: ~p\n", [Error])), aeso_errors:throw(aeso_errors:new(code_error, Pos, Msg)). +-spec internal_error(string()) -> no_return(). internal_error(Error) -> Msg = lists:flatten(io_lib:format("~p\n", [Error])), aeso_errors:throw(aeso_errors:new(internal_error, aeso_errors:pos(0, 0), Msg)). %% -- Pretty printing -------------------------------------------------------- +-spec format_fcode(fcode()) -> string(). format_fcode(#{ functions := Funs }) -> prettypr:format(format_funs(Funs)). +-spec format_funs(functions()) -> prettypr:document(). format_funs(Funs) -> pp_above( [ pp_fun(Name, Def) || {Name, Def} <- maps:to_list(Funs) ]). +-spec format_fexpr(fexpr()) -> string(). format_fexpr(E) -> prettypr:format(pp_fexpr(E)). +-spec pp_fun(fun_name(), fun_def()) -> prettypr:document(). pp_fun(Name, #{ args := Args, return := Return, body := Body }) -> PPArg = fun({X, T}) -> pp_beside([pp_text(X), pp_text(" : "), pp_ftype(T)]) end, pp_above(pp_beside([pp_text("function "), pp_fun_name(Name), @@ -2114,39 +2243,53 @@ pp_fun(Name, #{ args := Args, return := Return, body := Body }) -> pp_text(" : "), pp_ftype(Return), pp_text(" =")]), prettypr:nest(2, pp_fexpr(Body))). +-spec pp_fun_name(fun_name()) -> prettypr:document(). pp_fun_name(event) -> pp_text(event); pp_fun_name({entrypoint, E}) -> pp_text(binary_to_list(E)); pp_fun_name({local_fun, Q}) -> pp_text(string:join(Q, ".")). +-spec pp_text(binary() | string() | atom() | integer()) -> prettypr:document(). pp_text(<<>>) -> prettypr:text("\"\""); pp_text(Bin) when is_binary(Bin) -> prettypr:text(lists:flatten(io_lib:format("~p", [binary_to_list(Bin)]))); pp_text(S) when is_list(S) -> prettypr:text(lists:concat([S])); pp_text(A) when is_atom(A) -> prettypr:text(atom_to_list(A)); pp_text(N) when is_integer(N) -> prettypr:text(integer_to_list(N)). +-spec pp_int(integer()) -> prettypr:document(). pp_int(I) -> prettypr:text(integer_to_list(I)). +-spec pp_beside([prettypr:document()]) -> prettypr:document(). pp_beside([]) -> prettypr:empty(); pp_beside([X]) -> X; pp_beside([X | Xs]) -> pp_beside(X, pp_beside(Xs)). +-spec pp_beside(prettypr:document(), prettypr:document()) -> prettypr:document(). pp_beside(A, B) -> prettypr:beside(A, B). +-spec pp_above([prettypr:document()]) -> prettypr:document(). pp_above([]) -> prettypr:empty(); pp_above([X]) -> X; pp_above([X | Xs]) -> pp_above(X, pp_above(Xs)). +-spec pp_above(prettypr:document(), prettypr:document()) -> prettypr:document(). pp_above(A, B) -> prettypr:above(A, B). +-spec pp_parens(prettypr:document()) -> prettypr:document(). pp_parens(Doc) -> pp_beside([pp_text("("), Doc, pp_text(")")]). + +-spec pp_braces(prettypr:document()) -> prettypr:document(). pp_braces(Doc) -> pp_beside([pp_text("{"), Doc, pp_text("}")]). +-spec pp_punctuate(prettypr:document(), [prettypr:document()]) -> [prettypr:document()]. pp_punctuate(_Sep, []) -> []; pp_punctuate(_Sep, [X]) -> [X]; pp_punctuate(Sep, [X | Xs]) -> [pp_beside(X, Sep) | pp_punctuate(Sep, Xs)]. +-spec pp_par([prettypr:document()]) -> prettypr:document(). pp_par([]) -> prettypr:empty(); pp_par(Xs) -> prettypr:par(Xs). + +-spec pp_fexpr(fexpr()) -> prettypr:document(). pp_fexpr({lit, {typerep, T}}) -> pp_ftype(T); pp_fexpr({lit, {Tag, Lit}}) -> @@ -2223,9 +2366,11 @@ pp_fexpr({switch, Split}) -> pp_split(Split); pp_fexpr({contract_code, Contract}) -> pp_beside(pp_text("contract "), pp_text(Contract)). +-spec pp_call(prettypr:document(), [fexpr()]) -> prettypr:document(). pp_call(Fun, Args) -> pp_beside(Fun, pp_fexpr({tuple, Args})). +-spec pp_call_t(string(), [ftype()]) -> prettypr:document(). pp_call_t(Fun, Args) -> pp_beside(pp_text(Fun), pp_ftype({tuple, Args})). @@ -2251,15 +2396,18 @@ pp_ftype({variant, Cons}) -> _ -> pp_beside(pp_fexpr({con, [], I - 1, []}), pp_ftype({tuple, Args})) end || {I, Args} <- indexed(Cons)])). +-spec pp_split(fsplit()) -> prettypr:document(). pp_split({nosplit, E}) -> pp_fexpr(E); pp_split({split, Type, X, Alts}) -> pp_above([pp_beside([pp_text("switch("), pp_text(X), pp_text(" : "), pp_ftype(Type), pp_text(")")])] ++ [prettypr:nest(2, pp_case(Alt)) || Alt <- Alts]). +-spec pp_case(fcase()) -> prettypr:document(). pp_case({'case', Pat, Split}) -> prettypr:sep([pp_beside(pp_pat(Pat), pp_text(" =>")), prettypr:nest(2, pp_split(Split))]). +-spec pp_pat(fsplit_pat()) -> prettypr:document(). pp_pat({tuple, Xs}) -> pp_fexpr({tuple, [{var, X} || X <- Xs]}); pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, X}, {var, Xs}]}); pp_pat({con, As, I, Xs}) -> pp_fexpr({con, As, I, [{var, X} || X <- Xs]}); @@ -2268,6 +2416,7 @@ pp_pat(P = {Tag, _}) when Tag == bool; Tag == int; Tag == string -> pp_fexpr({lit, P}); pp_pat(Pat) -> pp_fexpr(Pat). +-spec is_infix(op()) -> boolean(). is_infix(Op) -> C = hd(atom_to_list(Op)), C < $a orelse C > $z. -- 2.30.2 From 5046c08b9faffdfc250c31eaa5f570606ba4ab3b Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 9 Nov 2022 12:58:02 +0300 Subject: [PATCH 15/92] Dead code removal --- src/aeso_ast_to_fcode.erl | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 8960c2a..a51b015 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -1546,7 +1546,6 @@ simplify(Env, {proj, _, {var, X}, I} = Expr) -> simplify(Env, {switch, Split}) -> case simpl_switch(Env, [], Split) of nomatch -> {builtin, abort, [{lit, {string, <<"Incomplete patterns">>}}]}; - stuck -> {switch, Split}; Expr -> Expr end; @@ -1596,21 +1595,17 @@ nest_catchalls([C = {'case', {var, _}, {nosplit, _}} | _]) -> C; nest_catchalls([{'case', P = {var, _}, {split, Type, X, Alts}} | Catchalls]) -> {'case', P, {split, Type, X, add_catchalls(Alts, Catchalls)}}. --spec simpl_switch(expr_env(), [fcase()], fsplit()) -> fexpr() | stuck | nomatch. +-spec simpl_switch(expr_env(), [fcase()], fsplit()) -> fexpr() | nomatch. simpl_switch(_Env, _, {nosplit, E}) -> E; simpl_switch(Env, Catchalls, {split, Type, X, Alts}) -> Alts1 = add_catchalls(Alts, Catchalls), Stuck = {switch, {split, Type, X, Alts1}}, case constructor_form(Env, {var, X}) of false -> Stuck; - E -> - case simpl_case(Env, E, Alts1) of - stuck -> Stuck; - Res -> Res - end + E -> simpl_case(Env, E, Alts1) end. --spec simpl_case(expr_env(), fexpr(), [fcase()]) -> fexpr() | stuck | nomatch. +-spec simpl_case(expr_env(), fexpr(), [fcase()]) -> fexpr() | nomatch. simpl_case(_, _, []) -> nomatch; simpl_case(Env, E, [{'case', Pat, Body} | Alts]) -> case match_pat(Pat, E) of @@ -1619,7 +1614,6 @@ simpl_case(Env, E, [{'case', Pat, Body} | Alts]) -> Env1 = maps:merge(Env, maps:from_list(Binds)), case simpl_switch(Env1, get_catchalls(Alts), Body) of nomatch -> simpl_case(Env, E, Alts); - stuck -> stuck; Body1 -> let_bind(Binds, Body1) end end. -- 2.30.2 From 431e983940586de7464a5ff810f2208a5172aa3b Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 9 Nov 2022 13:06:11 +0300 Subject: [PATCH 16/92] Fix the spec for compute_state_layout --- src/aeso_ast_to_fcode.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index a51b015..72be0e2 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -475,7 +475,7 @@ compute_state_layout(Env = #{ context := {contract_def, _} }, "state", Type) -> Env#{ state_layout => Layout }; compute_state_layout(Env, _, _) -> Env. --spec compute_state_layout(state_reg(), ftype()) -> {state_reg(), state_layout() | [state_layout()]}. +-spec compute_state_layout(state_reg(), ftype() | [ftype()]) -> {state_reg(), state_layout() | [state_layout()]}. compute_state_layout(R, {tuple, [T]}) -> compute_state_layout(R, T); compute_state_layout(R, {tuple, Ts}) -> -- 2.30.2 From 08174e5dbfafb1530cd97e3b0b32df0c9df3bbc7 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 9 Nov 2022 14:14:39 +0300 Subject: [PATCH 17/92] Add fann() to var --- src/aeso_ast_to_fcode.erl | 150 +++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 73 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 72be0e2..cf20357 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -62,7 +62,7 @@ -type fexpr() :: {lit, flit()} | nil - | {var, var_name()} + | {var, fann(), var_name()} | {def, fann(), fun_name(), [fexpr()]} | {remote, fann(), [ftype()], ftype(), fexpr(), fun_name(), [fexpr()]} | {builtin, builtin(), [fexpr()]} @@ -91,7 +91,7 @@ -type fcase() :: {'case', fsplit_pat(), fsplit()}. --type fsplit_pat() :: {var, var_name()} +-type fsplit_pat() :: {var, fann(), var_name()} | {bool, false | true} | {int, integer()} | {string, binary()} @@ -533,17 +533,18 @@ args_to_fcode(Env, Args) -> -spec make_let(fexpr(), fun((fexpr()) -> fexpr())) -> fexpr(). make_let(Expr, Body) -> case Expr of - {var, _} -> Body(Expr); + {var, _, _} -> Body(Expr); {lit, {int, _}} -> Body(Expr); {lit, {bool, _}} -> Body(Expr); _ -> X = fresh_name(), - {'let', get_fann(Expr), X, Expr, Body({var, X})} + FAnn = get_fann(Expr), + {'let', FAnn, X, Expr, Body({var, FAnn, X})} end. -spec let_bind(var_name(), fexpr(), fexpr()) -> fexpr(). -let_bind(X, {var, Y}, Body) -> rename([{X, Y}], Body); -let_bind(X, Expr, Body) -> {'let', get_fann(Expr), X, Expr, Body}. +let_bind(X, {var, _, Y}, Body) -> rename([{X, Y}], Body); +let_bind(X, Expr, Body) -> {'let', get_fann(Expr), X, Expr, Body}. -spec let_bind([{var_name(), fexpr()}], fexpr()) -> fexpr(). let_bind(Binds, Body) -> @@ -645,7 +646,7 @@ expr_to_fcode(Env, {record_t, [FieldT]}, {record, Ann, Rec, Fields}) -> expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) -> X = fresh_name(), FAnn = to_fann(Ann), - Proj = fun(I) -> {proj, FAnn, {var, X}, I - 1} end, + Proj = fun(I) -> {proj, FAnn, {var, FAnn, X}, I - 1} end, Comp = fun({I, false}) -> Proj(I); ({_, {set, E}}) -> expr_to_fcode(Env, E); ({I, {upd, Z, E}}) -> {'let', FAnn, Z, Proj(I), expr_to_fcode(bind_var(Env, Z), E)} @@ -659,7 +660,7 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) -> Updates = [ {I, field_value(FT, Fields)} || {I, FT} <- indexed(FieldTypes) ], Body = case Expand of true -> {tuple, lists:map(Comp, Updates)}; - false -> lists:foldr(Set, {var, X}, Updates) + false -> lists:foldr(Set, {var, FAnn, X}, Updates) end, {'let', FAnn, X, expr_to_fcode(Env, Rec), Body}; @@ -761,11 +762,11 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A %% FFun is a closure, with first component the function name and %% second component the environment FAnn = to_fann(Ann), - Call = fun(X) -> {funcall, FAnn, {proj, FAnn, {var, X}, 0}, [{proj, FAnn, {var, X}, 1} | FArgs]} end, + Call = fun(X) -> {funcall, FAnn, {proj, FAnn, {var, FAnn, X}, 0}, [{proj, FAnn, {var, FAnn, X}, 1} | FArgs]} end, case FFun of - {var, X} -> Call(X); - _ -> X = fresh_name(), - {'let', FAnn, X, FFun, Call(X)} + {var, _, X} -> Call(X); + _ -> X = fresh_name(), + {'let', FAnn, X, FFun, Call(X)} end end; @@ -813,21 +814,23 @@ expr_to_fcode(_Env, Type, Expr) -> error({todo, {Expr, ':', Type}}). -spec make_if(fexpr(), fexpr(), fexpr()) -> fexpr(). -make_if({var, X}, Then, Else) -> +make_if({var, _, X}, Then, Else) -> {switch, {split, boolean, X, [{'case', {bool, false}, {nosplit, Else}}, {'case', {bool, true}, {nosplit, Then}}]}}; make_if(Cond, Then, Else) -> X = fresh_name(), - {'let', get_fann(Cond), X, Cond, make_if({var, X}, Then, Else)}. + FAnn = get_fann(Cond), + {'let', FAnn, X, Cond, make_if({var, FAnn, X}, Then, Else)}. -spec make_if_no_else(fexpr(), fexpr()) -> fexpr(). -make_if_no_else({var, X}, Then) -> +make_if_no_else({var, _, X}, Then) -> {switch, {split, boolean, X, [{'case', {bool, true}, {nosplit, Then}}]}}; make_if_no_else(Cond, Then) -> X = fresh_name(), - {'let', get_fann(Cond), X, Cond, make_if_no_else({var, X}, Then)}. + FAnn = get_fann(Cond), + {'let', FAnn, X, Cond, make_if_no_else({var, FAnn, X}, Then)}. -spec make_tuple([fexpr()]) -> fexpr(). make_tuple([E]) -> E; @@ -858,7 +861,7 @@ alts_to_fcode(Env, Type, X, Alts, Switch) -> %% Intermediate format before case trees (fcase() and fsplit()). -type falt() :: {'case', [fpat()], fexpr()}. --type fpat() :: {var, var_name()} +-type fpat() :: {var, fann(), var_name()} | {bool, false | true} | {int, integer()} | {string, binary()} @@ -912,7 +915,7 @@ split_tree(Env, Vars, Alts = [{'case', Pats, Body} | _]) -> case next_split(Pats) of false -> Xs = [ X || {X, _} <- Vars ], - Ys = [ Y || {var, Y} <- Pats ], + Ys = [ Y || {var, _, Y} <- Pats ], Ren = [ {Y, X} || {Y, X} <- lists:zip(Ys, Xs), X /= Y, Y /= "_" ], %% TODO: Unreachable clauses error {nosplit, rename(Ren, Body)}; @@ -920,7 +923,7 @@ split_tree(Env, Vars, Alts = [{'case', Pats, Body} | _]) -> {Vars0, [{X, Type} | Vars1]} = lists:split(I - 1, Vars), Type1 = strip_singleton_tuples(Type), SAlts = merge_alts(I, X, [ split_alt(I, A) || A <- Alts ]), - MakeCase = fun({var, Z}, Split) -> {'case', {var, "_"}, rename_split([{Z, X}], Split)}; + MakeCase = fun({var, FAnn, Z}, Split) -> {'case', {var, FAnn, "_"}, rename_split([{Z, X}], Split)}; (SPat, Split) -> {'case', SPat, Split} end, Cases = [ MakeCase(SPat, split_tree(Env, Vars0 ++ split_vars(SPat, Type1) ++ Vars1, FAlts)) || {SPat, FAlts} <- SAlts ], @@ -942,7 +945,7 @@ merge_alts(I, X, Alts, Alts1) -> when Alts :: [{fsplit_pat(), [falt()]}]. merge_alt(_, _, {P, A}, []) -> [{P, [A]}]; merge_alt(I, X, {P, A}, [{Q, As} | Rest]) -> - Match = fun({var, _}, {var, _}) -> match; + Match = fun({var, _, _}, {var, _, _}) -> match; ({tuple, _}, {tuple, _}) -> match; ({bool, B}, {bool, B}) -> match; ({int, N}, {int, N}) -> match; @@ -951,8 +954,8 @@ merge_alt(I, X, {P, A}, [{Q, As} | Rest]) -> ({'::', _, _}, {'::', _, _}) -> match; ({con, _, C, _}, {con, _, C, _}) -> match; ({con, _, _, _}, {con, _, _, _}) -> mismatch; - ({var, _}, _) -> expand; - (_, {var, _}) -> insert; + ({var, _, _}, _) -> expand; + (_, {var, _, _}) -> insert; (_, _) -> mismatch end, case Match(P, Q) of @@ -966,11 +969,11 @@ merge_alt(I, X, {P, A}, [{Q, As} | Rest]) -> -spec expand(integer(), var_name(), fsplit_pat(), fsplit_pat(), falt()) -> term(). expand(I, X, P, Q, Case = {'case', Ps, E}) -> - {Ps0, [{var, Y} | Ps1]} = lists:split(I - 1, Ps), + {Ps0, [{var, _, Y} | Ps1]} = lists:split(I - 1, Ps), {Ps0r, Ren1} = rename_fpats([{Y, X} || Y /= X], Ps0), {Ps1r, Ren2} = rename_fpats(Ren1, Ps1), E1 = rename(Ren2, E), - Splice = fun(N) -> Ps0r ++ lists:duplicate(N, {var, "_"}) ++ Ps1r end, + Splice = fun(N) -> Ps0r ++ lists:duplicate(N, {var, [], "_"}) ++ Ps1r end, Type = fun({tuple, Xs}) -> {tuple, length(Xs)}; ({bool, _}) -> bool; ({int, _}) -> int; @@ -997,16 +1000,16 @@ split_alt(I, {'case', Pats, Body}) -> {SPat, {'case', Pats0 ++ InnerPats ++ Pats1, Body}}. -spec split_pat(fpat()) -> {fsplit_pat(), [fpat()]}. -split_pat(P = {var, _}) -> {{var, fresh_name()}, [P]}; -split_pat({bool, B}) -> {{bool, B}, []}; -split_pat({int, N}) -> {{int, N}, []}; -split_pat({string, N}) -> {{string, N}, []}; +split_pat(P = {var, FAnn, _}) -> {{var, FAnn, fresh_name()}, [P]}; +split_pat({bool, B}) -> {{bool, B}, []}; +split_pat({int, N}) -> {{int, N}, []}; +split_pat({string, N}) -> {{string, N}, []}; split_pat(nil) -> {nil, []}; split_pat({'::', P, Q}) -> {{'::', fresh_name(), fresh_name()}, [P, Q]}; split_pat({con, As, I, Pats}) -> Xs = [fresh_name() || _ <- Pats], {{con, As, I, Xs}, Pats}; -split_pat({assign, X = {var, _}, P}) -> +split_pat({assign, X = {var, _, _}, P}) -> {{assign, fresh_name(), fresh_name()}, [X, P]}; split_pat({tuple, Pats}) -> Xs = [fresh_name() || _ <- Pats], @@ -1023,11 +1026,11 @@ split_vars({con, _, I, Xs}, {variant, Cons}) -> lists:zip(Xs, lists:nth(I + 1, Cons)); split_vars({tuple, Xs}, {tuple, Ts}) -> lists:zip(Xs, Ts); -split_vars({var, X}, T) -> [{X, T}]. +split_vars({var, _, X}, T) -> [{X, T}]. -spec next_split([fpat()]) -> integer() | false. next_split(Pats) -> - IsVar = fun({var, _}) -> true; (_) -> false end, + IsVar = fun({var, _, _}) -> true; (_) -> false end, case [ I || {I, P} <- indexed(Pats), not IsVar(P) ] of [] -> false; [I | _] -> I @@ -1046,7 +1049,7 @@ pat_to_fcode(Env, Pat) -> pat_to_fcode(Env, no_type, Pat). -spec pat_to_fcode(env(), aeso_syntax:type() | no_type, aeso_syntax:pat()) -> fpat(). -pat_to_fcode(_Env, _Type, {id, _, X}) -> {var, X}; +pat_to_fcode(_Env, _Type, {id, Ann, X}) -> {var, to_fann(Ann), X}; pat_to_fcode(Env, _Type, {C, _, _} = Con) when C == con; C == qcon -> #con_tag{tag = I, arities = As} = lookup_con(Env, Con), {con, As, I, []}; @@ -1250,9 +1253,9 @@ event_function(_Env = #{event_type := {variant_t, EventCons}}, EventType = {vari Payload = case [ V || {notindexed, V} <- IVars ] of [] -> {lit, {string, <<>>}}; - [V] -> {var, V} + [V] -> {var, [], V} end, - Indices = [ {var, V} || {indexed, V} <- IVars ], + Indices = [ {var, [], V} || {indexed, V} <- IVars ], Body = {builtin, chain_event, [Payload, Hash | Indices]}, {'case', {con, Arities, Tag, Vars}, {nosplit, Body}} end, @@ -1300,7 +1303,8 @@ lifted_fun([Z], Xs, Body) -> body => Body }; lifted_fun(FVs, Xs, Body) -> Z = "%env", - Proj = fun({I, Y}, E) -> {'let', get_fann(Body), Y, {proj, get_fann(Body), {var, Z}, I - 1}, E} end, + FAnn = get_fann(Body), + Proj = fun({I, Y}, E) -> {'let', get_fann(Body), Y, {proj, FAnn, {var, FAnn, Z}, I - 1}, E} end, #{ attrs => [private], args => [{Z, any} | [{X, any} || X <- Xs]], return => any, @@ -1312,7 +1316,7 @@ lifted_fun(FVs, Xs, Body) -> make_closure(FVs, Xs, Body) -> Fun = add_lambda_fun(lifted_fun(FVs, Xs, Body)), Tup = fun([Y]) -> Y; (Ys) -> {tuple, Ys} end, - {closure, get_fann(Body), Fun, Tup([{var, Y} || Y <- FVs])}. + {closure, get_fann(Body), Fun, Tup([{var, [], Y} || Y <- FVs])}. -spec lambda_lift_expr(state_layout(), fexpr()) -> Closure when Closure :: fexpr(). @@ -1326,7 +1330,7 @@ lambda_lift_expr(Layout, UExpr) when element(1, UExpr) == def_u; element(1, UExp _ -> [] end, Xs = [ lists:concat(["arg", I]) || I <- lists:seq(1, Ar) ], - Args = [{var, X} || X <- Xs] ++ ExtraArgs, + Args = [{var, [], X} || X <- Xs] ++ ExtraArgs, Body = case Tag of builtin_u -> builtin_to_fcode(Layout, F, Args); def_u -> {def, [], F, Args} @@ -1337,13 +1341,13 @@ lambda_lift_expr(Layout, {remote_u, Ann, ArgsT, RetT, Ct, F}) -> Ct1 = lambda_lift_expr(Layout, Ct), NamedArgCount = 3, Xs = [ lists:concat(["arg", I]) || I <- lists:seq(1, length(ArgsT) + NamedArgCount) ], - Args = [{var, X} || X <- Xs], + Args = [{var, [], X} || X <- Xs], make_closure(FVs, Xs, {remote, Ann, ArgsT, RetT, Ct1, F, Args}); lambda_lift_expr(Layout, Expr) -> case Expr of {lit, _} -> Expr; nil -> Expr; - {var, _} -> Expr; + {var, _, _} -> Expr; {closure, _, _, _} -> Expr; {def, Ann, D, As} -> {def, Ann, D, lambda_lift_exprs(Layout, As)}; {builtin, B, As} -> {builtin, B, lambda_lift_exprs(Layout, As)}; @@ -1436,7 +1440,7 @@ make_lets(Es, Body) -> make_lets(Es, [], Body). -spec make_lets([fexpr()], [fexpr()], fun(([fexpr()]) -> fexpr())) -> fexpr(). make_lets([], Xs, Body) -> Body(lists:reverse(Xs)); -make_lets([{var, _} = E | Es], Xs, Body) -> +make_lets([{var, _, _} = E | Es], Xs, Body) -> make_lets(Es, [E | Xs], Body); make_lets([{lit, _} = E | Es], Xs, Body) -> make_lets(Es, [E | Xs], Body); @@ -1450,7 +1454,7 @@ inline_local_functions(Expr) -> bottom_up(fun inline_local_functions/2, Expr). -spec inline_local_functions(expr_env(), fexpr()) -> fexpr(). -inline_local_functions(Env, {funcall, _, {proj, _, {var, Y}, 0}, [{proj, _, {var, Y}, 1} | Args]} = Expr) -> +inline_local_functions(Env, {funcall, _, {proj, _, {var, _, Y}, 0}, [{proj, _, {var, _, Y}, 1} | Args]} = Expr) -> %% TODO: Don't always inline local funs? case maps:get(Y, Env, free) of {lam, _, Xs, Body} -> let_bind(lists:zip(Xs, Args), Body); @@ -1522,7 +1526,7 @@ simplify(_Env, {proj, FAnn, {tuple, Es}, I}) -> It = lists:nth(I + 1, Es), X = fresh_name(), Dup = safe_to_duplicate(It), - Val = if Dup -> It; true -> {var, X} end, + Val = if Dup -> It; true -> {var, FAnn, X} end, lists:foldr( fun({J, E}, Rest) when I == J -> case Dup of @@ -1537,8 +1541,8 @@ simplify(_Env, {proj, FAnn, {tuple, Es}, I}) -> end, Val, indexed(Es)); %% let x = e in .. x.i .. -simplify(Env, {proj, _, {var, X}, I} = Expr) -> - case simpl_proj(Env, I, {var, X}) of +simplify(Env, {proj, _, Var = {var, _, _}, I} = Expr) -> + case simpl_proj(Env, I, Var) of false -> Expr; E -> E end; @@ -1560,7 +1564,7 @@ simpl_proj(Env, I, Expr) -> end end, case Expr of false -> false; - {var, X} -> simpl_proj(Env, I, maps:get(X, Env, false)); + {var, _, X} -> simpl_proj(Env, I, maps:get(X, Env, false)); {tuple, Es} -> IfSafe(lists:nth(I + 1, Es)); {set_proj, _, _, I, Val} -> IfSafe(Val); {set_proj, _, E, _, _} -> simpl_proj(Env, I, E); @@ -1570,7 +1574,7 @@ simpl_proj(Env, I, Expr) -> -spec get_catchalls([fcase()]) -> [fcase()]. get_catchalls(Alts) -> - [ C || C = {'case', {var, _}, _} <- Alts ]. + [ C || C = {'case', {var, _, _}, _} <- Alts ]. %% The scode compiler can't handle multiple catch-alls, so we need to nest them %% inside each other. Instead of @@ -1583,7 +1587,7 @@ get_catchalls(Alts) -> -spec add_catchalls([fcase()], [fcase()]) -> [fcase()]. add_catchalls(Alts, []) -> Alts; add_catchalls(Alts, Catchalls) -> - case lists:splitwith(fun({'case', {var, _}, _}) -> false; (_) -> true end, + case lists:splitwith(fun({'case', {var, _, _}, _}) -> false; (_) -> true end, Alts) of {Alts1, [C]} -> Alts1 ++ [nest_catchalls([C | Catchalls])]; {_, []} -> Alts ++ [nest_catchalls(Catchalls)] @@ -1591,8 +1595,8 @@ add_catchalls(Alts, Catchalls) -> end. -spec nest_catchalls([fcase()]) -> fcase(). -nest_catchalls([C = {'case', {var, _}, {nosplit, _}} | _]) -> C; -nest_catchalls([{'case', P = {var, _}, {split, Type, X, Alts}} | Catchalls]) -> +nest_catchalls([C = {'case', {var, _, _}, {nosplit, _}} | _]) -> C; +nest_catchalls([{'case', P = {var, _, _}, {split, Type, X, Alts}} | Catchalls]) -> {'case', P, {split, Type, X, add_catchalls(Alts, Catchalls)}}. -spec simpl_switch(expr_env(), [fcase()], fsplit()) -> fexpr() | nomatch. @@ -1600,7 +1604,7 @@ simpl_switch(_Env, _, {nosplit, E}) -> E; simpl_switch(Env, Catchalls, {split, Type, X, Alts}) -> Alts1 = add_catchalls(Alts, Catchalls), Stuck = {switch, {split, Type, X, Alts1}}, - case constructor_form(Env, {var, X}) of + case constructor_form(Env, {var, [], X}) of false -> Stuck; E -> simpl_case(Env, E, Alts1) end. @@ -1624,14 +1628,14 @@ match_pat({con, _, C, Xs}, {con, _, C, Es}) -> lists:zip(Xs, Es); match_pat(L, {lit, L}) -> []; match_pat(nil, nil) -> []; match_pat({'::', X, Y}, {op, _, '::', [A, B]}) -> [{X, A}, {Y, B}]; -match_pat({var, X}, E) -> [{X, E}]; +match_pat({var, _, X}, E) -> [{X, E}]; match_pat({assign, X, P}, E) -> [{X, E}, {P, E}]; match_pat(_, _) -> false. -spec constructor_form(expr_env(), fexpr()) -> fexpr() | false. constructor_form(Env, Expr) -> case Expr of - {var, X} -> + {var, _, X} -> case maps:get(X, Env, free) of free -> false; E -> constructor_form(Env, E) %% TODO: shadowing? @@ -1672,14 +1676,14 @@ drop_unused_lets(_, Expr) -> Expr. -spec safe_to_duplicate(fexpr()) -> boolean(). safe_to_duplicate({lit, _}) -> true; -safe_to_duplicate({var, _}) -> true; +safe_to_duplicate({var, _, _}) -> true; safe_to_duplicate(nil) -> true; safe_to_duplicate({tuple, []}) -> true; safe_to_duplicate(_) -> false. -spec read_only(fexpr() | fsplit() | fcase() | [fexpr()] | [fcase()]) -> boolean(). read_only({lit, _}) -> true; -read_only({var, _}) -> true; +read_only({var, _, _}) -> true; read_only(nil) -> true; read_only({con, _, _, Es}) -> read_only(Es); read_only({tuple, Es}) -> read_only(Es); @@ -1832,7 +1836,7 @@ bind_var(Env = #{ vars := Vars }, X) -> Env#{ vars := [X | Vars] }. -spec resolve_var(env(), [aeso_syntax:name()]) -> fexpr(). resolve_var(#{ vars := Vars } = Env, [X]) -> case lists:member(X, Vars) of - true -> {var, X}; + true -> {var, [], X}; false -> case resolve_const(Env, [X]) of false -> resolve_fun(Env, [X]); @@ -1900,7 +1904,7 @@ fresh_name(Prefix) -> lists:concat([Prefix, N]). -spec pat_vars(fpat()) -> [var_name()]. -pat_vars({var, X}) -> [X || X /= "_"]; +pat_vars({var, _, X}) -> [X || X /= "_"]; pat_vars({bool, _}) -> []; pat_vars({int, _}) -> []; pat_vars({string, _}) -> []; @@ -1912,7 +1916,7 @@ pat_vars({assign, X, P}) -> pat_vars(X) ++ pat_vars(P); pat_vars(Ps) when is_list(Ps) -> [X || P <- Ps, X <- pat_vars(P)]. -spec fsplit_pat_vars(fsplit_pat()) -> [var_name()]. -fsplit_pat_vars({var, X}) -> [X || X /= "_"]; +fsplit_pat_vars({var, _, X}) -> [X || X /= "_"]; fsplit_pat_vars({bool, _}) -> []; fsplit_pat_vars({int, _}) -> []; fsplit_pat_vars({string, _}) -> []; @@ -1926,7 +1930,7 @@ free_vars(Xs) when is_list(Xs) -> lists:umerge([ free_vars(X) || X <- Xs ]); free_vars(Expr) -> case Expr of - {var, X} -> [X]; + {var, _, X} -> [X]; {lit, _} -> []; nil -> []; {def, _, _, As} -> free_vars(As); @@ -1948,7 +1952,7 @@ free_vars(Expr) -> {lam, _, Xs, B} -> free_vars(B) -- lists:sort(Xs); {closure, _, _, A} -> free_vars(A); {switch, A} -> free_vars(A); - {split, _, X, As} -> free_vars([{var, X} | As]); + {split, _, X, As} -> free_vars([{var, [], X} | As]); {nosplit, A} -> free_vars(A); {'case', P, A} -> free_vars(A) -- lists:sort(fsplit_pat_vars(P)) end. @@ -1958,7 +1962,7 @@ used_defs(Xs) when is_list(Xs) -> lists:umerge([ used_defs(X) || X <- Xs ]); used_defs(Expr) -> case Expr of - {var, _} -> []; + {var, _, _} -> []; {lit, _} -> []; nil -> []; {def, _, F, As} -> lists:umerge([F], used_defs(As)); @@ -1995,7 +1999,7 @@ bottom_up(F, Env, Expr) -> F(Env, case Expr of {lit, _} -> Expr; nil -> Expr; - {var, _} -> Expr; + {var, _, _} -> Expr; {def, Ann, D, Es} -> {def, Ann, D, [bottom_up(F, Env, E) || E <- Es]}; {def_u, _, _, _} -> Expr; {builtin, B, Es} -> {builtin, B, [bottom_up(F, Env, E) || E <- Es]}; @@ -2055,7 +2059,7 @@ rename(Ren, Expr) -> case Expr of {lit, _} -> Expr; nil -> nil; - {var, X} -> {var, rename_var(Ren, X)}; + {var, Ann, X} -> {var, Ann, rename_var(Ren, X)}; {def, Ann, D, Es} -> {def, Ann, D, [rename(Ren, E) || E <- Es]}; {def_u, _, _, _} -> Expr; {builtin, B, Es} -> {builtin, B, [rename(Ren, E) || E <- Es]}; @@ -2117,9 +2121,9 @@ rename_fpat(Ren, {'::', P, Q}) -> {P1, Ren1} = rename_fpat(Ren, P), {Q1, Ren2} = rename_fpat(Ren1, Q), {{'::', P1, Q1}, Ren2}; -rename_fpat(Ren, {var, X}) -> +rename_fpat(Ren, {var, Ann, X}) -> {Z, Ren1} = rename_binding(Ren, X), - {{var, Z}, Ren1}; + {{var, Ann, Z}, Ren1}; rename_fpat(Ren, {con, Ar, C, Ps}) -> {Ps1, Ren1} = rename_fpats(Ren, Ps), {{con, Ar, C, Ps1}, Ren1}; @@ -2136,9 +2140,9 @@ rename_spat(Ren, {'::', X, Y}) -> {X1, Ren1} = rename_binding(Ren, X), {Y1, Ren2} = rename_binding(Ren1, Y), {{'::', X1, Y1}, Ren2}; -rename_spat(Ren, {var, X}) -> +rename_spat(Ren, {var, Ann, X}) -> {Z, Ren1} = rename_binding(Ren, X), - {{var, Z}, Ren1}; + {{var, Ann, Z}, Ren1}; rename_spat(Ren, {con, Ar, C, Xs}) -> {Zs, Ren1} = rename_bindings(Ren, Xs), {{con, Ar, C, Zs}, Ren1}; @@ -2290,7 +2294,7 @@ pp_fexpr({lit, {Tag, Lit}}) -> aeso_pretty:expr({Tag, [], Lit}); pp_fexpr(nil) -> pp_text("[]"); -pp_fexpr({var, X}) -> pp_text(X); +pp_fexpr({var, _, X}) -> pp_text(X); pp_fexpr({def, Fun}) -> pp_fun_name(Fun); pp_fexpr({def_u, _, Fun, Ar}) -> pp_beside([pp_fun_name(Fun), pp_text("/"), pp_int(Ar)]); @@ -2306,12 +2310,12 @@ pp_fexpr({tuple, Es}) -> pp_fexpr({proj, _, E, I}) -> pp_beside([pp_fexpr(E), pp_text("."), pp_int(I)]); pp_fexpr({lam, _, Xs, A}) -> - pp_par([pp_fexpr({tuple, [{var, X} || X <- Xs]}), pp_text("=>"), + pp_par([pp_fexpr({tuple, [{var, [], X} || X <- Xs]}), pp_text("=>"), prettypr:nest(2, pp_fexpr(A))]); pp_fexpr({closure, _, Fun, ClEnv}) -> FVs = case ClEnv of {tuple, Xs} -> Xs; - {var, _} -> [ClEnv] + {var, _, _} -> [ClEnv] end, pp_call(pp_text("__CLOSURE__"), [{def, Fun} | FVs]); pp_fexpr({set_proj, _, E, I, A}) -> @@ -2402,10 +2406,10 @@ pp_case({'case', Pat, Split}) -> prettypr:nest(2, pp_split(Split))]). -spec pp_pat(fsplit_pat()) -> prettypr:document(). -pp_pat({tuple, Xs}) -> pp_fexpr({tuple, [{var, X} || X <- Xs]}); -pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, X}, {var, Xs}]}); -pp_pat({con, As, I, Xs}) -> pp_fexpr({con, As, I, [{var, X} || X <- Xs]}); -pp_pat({var, X}) -> pp_fexpr({var, X}); +pp_pat({tuple, Xs}) -> pp_fexpr({tuple, [{var, [], X} || X <- Xs]}); +pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, [], X}, {var, [], Xs}]}); +pp_pat({con, As, I, Xs}) -> pp_fexpr({con, As, I, [{var, [], X} || X <- Xs]}); +pp_pat({var, Ann, X}) -> pp_fexpr({var, Ann, X}); pp_pat(P = {Tag, _}) when Tag == bool; Tag == int; Tag == string -> pp_fexpr({lit, P}); pp_pat(Pat) -> pp_fexpr(Pat). -- 2.30.2 From d11f3107a4f6a65fdd3366d0d999aa66c94c5ea7 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 9 Nov 2022 14:17:42 +0300 Subject: [PATCH 18/92] Add fann() to switch --- src/aeso_ast_to_fcode.erl | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index cf20357..ea52a4e 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -74,7 +74,7 @@ | {'let', fann(), var_name(), fexpr(), fexpr()} | {funcall, fann(), fexpr(), [fexpr()]} %% Call to unknown function | {closure, fann(), fun_name(), fexpr()} - | {switch, fsplit()} + | {switch, fann(), fsplit()} | {set_state, fann(), state_reg(), fexpr()} | {get_state, state_reg()} %% The following (unapplied top-level functions/builtins and @@ -702,7 +702,7 @@ expr_to_fcode(Env, _Type, {'if', _, Cond, Then, Else}) -> %% Switch expr_to_fcode(Env, _, S = {switch, Ann, Expr = {typed, _, E, Type}, Alts}) -> Switch = fun(X) -> - {switch, alts_to_fcode(Env, type_to_fcode(Env, Type), X, Alts, S)} + {switch, to_fann(Ann), alts_to_fcode(Env, type_to_fcode(Env, Type), X, Alts, S)} end, case E of {id, _, X} -> Switch(X); @@ -814,8 +814,8 @@ expr_to_fcode(_Env, Type, Expr) -> error({todo, {Expr, ':', Type}}). -spec make_if(fexpr(), fexpr(), fexpr()) -> fexpr(). -make_if({var, _, X}, Then, Else) -> - {switch, {split, boolean, X, +make_if({var, FAnn, X}, Then, Else) -> + {switch, FAnn, {split, boolean, X, [{'case', {bool, false}, {nosplit, Else}}, {'case', {bool, true}, {nosplit, Then}}]}}; make_if(Cond, Then, Else) -> @@ -824,8 +824,8 @@ make_if(Cond, Then, Else) -> {'let', FAnn, X, Cond, make_if({var, FAnn, X}, Then, Else)}. -spec make_if_no_else(fexpr(), fexpr()) -> fexpr(). -make_if_no_else({var, _, X}, Then) -> - {switch, {split, boolean, X, +make_if_no_else({var, FAnn, X}, Then) -> + {switch, FAnn, {split, boolean, X, [{'case', {bool, true}, {nosplit, Then}}]}}; make_if_no_else(Cond, Then) -> X = fresh_name(), @@ -1114,8 +1114,8 @@ decision_tree_to_fcode({atom, B}) -> B; decision_tree_to_fcode({'if', A, Then, Else}) -> X = fresh_name(), {'let', [], X, A, - {switch, {split, boolean, X, [{'case', {bool, false}, {nosplit, decision_tree_to_fcode(Else)}}, - {'case', {bool, true}, {nosplit, decision_tree_to_fcode(Then)}}]}}}. + {switch, [], {split, boolean, X, [{'case', {bool, false}, {nosplit, decision_tree_to_fcode(Else)}}, + {'case', {bool, true}, {nosplit, decision_tree_to_fcode(Then)}}]}}}. %% -- Statements -- @@ -1262,7 +1262,7 @@ event_function(_Env = #{event_type := {variant_t, EventCons}}, EventType = {vari #{ attrs => [private], args => [{"e", EventType}], return => {tuple, []}, - body => {switch, {split, EventType, "e", lists:map(Case, Cons)}} }. + body => {switch, [], {split, EventType, "e", lists:map(Case, Cons)}} }. %% -- Lambda lifting --------------------------------------------------------- %% The expr_to_fcode compiler lambda expressions to {lam, Xs, Body}, but in @@ -1361,7 +1361,7 @@ lambda_lift_expr(Layout, Expr) -> {funcall, Ann, A, Bs} -> {funcall, Ann, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)}; {set_state, Ann, R, A} -> {set_state, Ann, R, lambda_lift_expr(Layout, A)}; {get_state, _} -> Expr; - {switch, S} -> {switch, lambda_lift_expr(Layout, S)}; + {switch, Ann, S} -> {switch, Ann, lambda_lift_expr(Layout, S)}; {split, Type, X, Alts} -> {split, Type, X, lambda_lift_exprs(Layout, Alts)}; {nosplit, A} -> {nosplit, lambda_lift_expr(Layout, A)}; {'case', P, S} -> {'case', P, lambda_lift_expr(Layout, S)} @@ -1547,7 +1547,7 @@ simplify(Env, {proj, _, Var = {var, _, _}, I} = Expr) -> E -> E end; -simplify(Env, {switch, Split}) -> +simplify(Env, {switch, _, Split}) -> case simpl_switch(Env, [], Split) of nomatch -> {builtin, abort, [{lit, {string, <<"Incomplete patterns">>}}]}; Expr -> Expr @@ -1603,7 +1603,7 @@ nest_catchalls([{'case', P = {var, _, _}, {split, Type, X, Alts}} | Catchalls]) simpl_switch(_Env, _, {nosplit, E}) -> E; simpl_switch(Env, Catchalls, {split, Type, X, Alts}) -> Alts1 = add_catchalls(Alts, Catchalls), - Stuck = {switch, {split, Type, X, Alts1}}, + Stuck = {switch, [], {split, Type, X, Alts1}}, case constructor_form(Env, {var, [], X}) of false -> Stuck; E -> simpl_case(Env, E, Alts1) @@ -1700,7 +1700,7 @@ read_only({lam, _, _, _}) -> true; read_only({def, _, _, _}) -> false; %% TODO: purity analysis read_only({remote, _, _, _, _, _, _}) -> false; read_only({builtin, _, _}) -> false; %% TODO: some builtins are -read_only({switch, Split}) -> read_only(Split); +read_only({switch, _, Split}) -> read_only(Split); read_only({split, _, _, Cases}) -> read_only(Cases); read_only({nosplit, E}) -> read_only(E); read_only({'case', _, Split}) -> read_only(Split); @@ -1951,7 +1951,7 @@ free_vars(Expr) -> {get_state, _} -> []; {lam, _, Xs, B} -> free_vars(B) -- lists:sort(Xs); {closure, _, _, A} -> free_vars(A); - {switch, A} -> free_vars(A); + {switch, _, A} -> free_vars(A); {split, _, X, As} -> free_vars([{var, [], X} | As]); {nosplit, A} -> free_vars(A); {'case', P, A} -> free_vars(A) -- lists:sort(fsplit_pat_vars(P)) @@ -1983,7 +1983,7 @@ used_defs(Expr) -> {get_state, _} -> []; {lam, _, _, B} -> used_defs(B); {closure, _, F, A} -> lists:umerge([F], used_defs(A)); - {switch, A} -> used_defs(A); + {switch, _, A} -> used_defs(A); {split, _, _, As} -> used_defs(As); {nosplit, A} -> used_defs(A); {'case', _, A} -> used_defs(A) @@ -2016,7 +2016,7 @@ bottom_up(F, Env, Expr) -> {set_state, Ann, R, E} -> {set_state, Ann, R, bottom_up(F, Env, E)}; {get_state, _} -> Expr; {closure, Ann, F, CEnv} -> {closure, Ann, F, bottom_up(F, Env, CEnv)}; - {switch, Split} -> {switch, bottom_up(F, Env, Split)}; + {switch, Ann, Split} -> {switch, Ann, bottom_up(F, Env, Split)}; {lam, Ann, Xs, B} -> {lam, Ann, Xs, bottom_up(F, Env, B)}; {'let', Ann, X, E, Body} -> E1 = bottom_up(F, Env, E), @@ -2076,7 +2076,7 @@ rename(Ren, Expr) -> {set_state, Ann, R, E} -> {set_state, Ann, R, rename(Ren, E)}; {get_state, _} -> Expr; {closure, Ann, F, Env} -> {closure, Ann, F, rename(Ren, Env)}; - {switch, Split} -> {switch, rename_split(Ren, Split)}; + {switch, Ann, Split} -> {switch, Ann, rename_split(Ren, Split)}; {lam, Ann, Xs, B} -> {Zs, Ren1} = rename_bindings(Ren, Xs), {lam, Ann, Zs, rename(Ren1, B)}; @@ -2360,7 +2360,7 @@ pp_fexpr({set_state, _, R, A}) -> pp_call(pp_text("set_state"), [{lit, {int, R}}, A]); pp_fexpr({get_state, R}) -> pp_call(pp_text("get_state"), [{lit, {int, R}}]); -pp_fexpr({switch, Split}) -> pp_split(Split); +pp_fexpr({switch, _, Split}) -> pp_split(Split); pp_fexpr({contract_code, Contract}) -> pp_beside(pp_text("contract "), pp_text(Contract)). -- 2.30.2 From 7abf93e0e0fef3429de3aaea9d8caec52387f417 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 9 Nov 2022 14:28:27 +0300 Subject: [PATCH 19/92] Add fann() to lit and get_state --- src/aeso_ast_to_fcode.erl | 136 +++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index ea52a4e..d94d5fd 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -60,7 +60,7 @@ -type fann() :: [ {line, aeso_syntax:ann_line()} ]. --type fexpr() :: {lit, flit()} +-type fexpr() :: {lit, fann(), flit()} | nil | {var, fann(), var_name()} | {def, fann(), fun_name(), [fexpr()]} @@ -76,7 +76,7 @@ | {closure, fann(), fun_name(), fexpr()} | {switch, fann(), fsplit()} | {set_state, fann(), state_reg(), fexpr()} - | {get_state, state_reg()} + | {get_state, fann(), state_reg()} %% The following (unapplied top-level functions/builtins and %% lambdas) are generated by the fcode compiler, but translated %% to closures by the lambda lifter. @@ -533,9 +533,9 @@ args_to_fcode(Env, Args) -> -spec make_let(fexpr(), fun((fexpr()) -> fexpr())) -> fexpr(). make_let(Expr, Body) -> case Expr of - {var, _, _} -> Body(Expr); - {lit, {int, _}} -> Body(Expr); - {lit, {bool, _}} -> Body(Expr); + {var, _, _} -> Body(Expr); + {lit, _, {int, _}} -> Body(Expr); + {lit, _, {bool, _}} -> Body(Expr); _ -> X = fresh_name(), FAnn = get_fann(Expr), @@ -560,39 +560,39 @@ expr_to_fcode(Env, Expr) -> -spec expr_to_fcode(env(), aeso_syntax:type() | no_type, aeso_syntax:expr()) -> fexpr(). %% Literals -expr_to_fcode(_Env, _Type, {int, _, N}) -> {lit, {int, N}}; -expr_to_fcode(_Env, _Type, {char, _, N}) -> {lit, {int, N}}; -expr_to_fcode(_Env, _Type, {bool, _, B}) -> {lit, {bool, B}}; -expr_to_fcode(_Env, _Type, {string, _, S}) -> {lit, {string, S}}; -expr_to_fcode(_Env, _Type, {account_pubkey, _, K}) -> {lit, {account_pubkey, K}}; -expr_to_fcode(_Env, _Type, {contract_pubkey, _, K}) -> {lit, {contract_pubkey, K}}; -expr_to_fcode(_Env, _Type, {oracle_pubkey, _, K}) -> {lit, {oracle_pubkey, K}}; -expr_to_fcode(_Env, _Type, {oracle_query_id, _, K}) -> {lit, {oracle_query_id, K}}; -expr_to_fcode(_Env, _Type, {bytes, _, B}) -> {lit, {bytes, B}}; +expr_to_fcode(_Env, _Type, {int, Ann, N}) -> {lit, to_fann(Ann), {int, N}}; +expr_to_fcode(_Env, _Type, {char, Ann, N}) -> {lit, to_fann(Ann), {int, N}}; +expr_to_fcode(_Env, _Type, {bool, Ann, B}) -> {lit, to_fann(Ann), {bool, B}}; +expr_to_fcode(_Env, _Type, {string, Ann, S}) -> {lit, to_fann(Ann), {string, S}}; +expr_to_fcode(_Env, _Type, {account_pubkey, Ann, K}) -> {lit, to_fann(Ann), {account_pubkey, K}}; +expr_to_fcode(_Env, _Type, {contract_pubkey, Ann, K}) -> {lit, to_fann(Ann), {contract_pubkey, K}}; +expr_to_fcode(_Env, _Type, {oracle_pubkey, Ann, K}) -> {lit, to_fann(Ann), {oracle_pubkey, K}}; +expr_to_fcode(_Env, _Type, {oracle_query_id, Ann, K}) -> {lit, to_fann(Ann), {oracle_query_id, K}}; +expr_to_fcode(_Env, _Type, {bytes, Ann, B}) -> {lit, to_fann(Ann), {bytes, B}}; %% Variables expr_to_fcode(Env, _Type, {id, _, X}) -> resolve_var(Env, [X]); expr_to_fcode(Env, Type, {qid, _, X}) -> case resolve_var(Env, X) of - {builtin_u, Ann, B, Ar} when B =:= oracle_query; - B =:= oracle_get_question; - B =:= oracle_get_answer; - B =:= oracle_respond; - B =:= oracle_register; - B =:= oracle_check; - B =:= oracle_check_query -> + {builtin_u, FAnn, B, Ar} when B =:= oracle_query; + B =:= oracle_get_question; + B =:= oracle_get_answer; + B =:= oracle_respond; + B =:= oracle_register; + B =:= oracle_check; + B =:= oracle_check_query -> OType = get_oracle_type(B, Type), {oracle, QType, RType} = type_to_fcode(Env, OType), - TypeArgs = [{lit, {typerep, QType}}, {lit, {typerep, RType}}], - {builtin_u, Ann, B, Ar, TypeArgs}; - {builtin_u, Ann, B = aens_resolve, Ar} -> + TypeArgs = [{lit, FAnn, {typerep, QType}}, {lit, FAnn, {typerep, RType}}], + {builtin_u, FAnn, B, Ar, TypeArgs}; + {builtin_u, FAnn, B = aens_resolve, Ar} -> {fun_t, _, _, _, ResType} = Type, AensType = type_to_fcode(Env, ResType), - TypeArgs = [{lit, {typerep, AensType}}], - {builtin_u, Ann, B, Ar, TypeArgs}; - {builtin_u, Ann, B = bytes_split, Ar} -> + TypeArgs = [{lit, FAnn, {typerep, AensType}}], + {builtin_u, FAnn, B, Ar, TypeArgs}; + {builtin_u, FAnn, B = bytes_split, Ar} -> {fun_t, _, _, _, {tuple_t, _, [{bytes_t, _, N}, _]}} = Type, - {builtin_u, Ann, B, Ar, [{lit, {int, N}}]}; + {builtin_u, FAnn, B, Ar, [{lit, FAnn, {int, N}}]}; Other -> Other end; @@ -728,7 +728,7 @@ expr_to_fcode(Env, Type, {app, Ann, {Op, _}, [A, B]}) when is_atom(Op) -> expr_to_fcode(Env, _Type, {app, Ann, {Op, _}, [A]}) when is_atom(Op) -> FAnn = to_fann(Ann), case Op of - '-' -> {op, FAnn, '-', [{lit, {int, 0}}, expr_to_fcode(Env, A)]}; + '-' -> {op, FAnn, '-', [{lit, FAnn, {int, 0}}, expr_to_fcode(Env, A)]}; '!' -> {op, FAnn, '!', [expr_to_fcode(Env, A)]} end; @@ -737,27 +737,27 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A Args1 = get_named_args(NamedArgsT, Args), FArgs = [expr_to_fcode(Env, Arg) || Arg <- Args1], case expr_to_fcode(Env, Fun) of - {builtin_u, Ann, B, _Ar, TypeArgs} -> builtin_to_fcode(state_layout(Env), B, FArgs ++ TypeArgs); - {builtin_u, Ann, chain_clone, _Ar} -> + {builtin_u, _, B, _Ar, TypeArgs} -> builtin_to_fcode(state_layout(Env), B, FArgs ++ TypeArgs); + {builtin_u, FAnn, chain_clone, _Ar} -> case ArgsT of var_args -> fcode_error({var_args_not_set, FunE}); _ -> %% Here we little cheat on the typechecker, but this inconsistency %% is to be solved in `aeso_fcode_to_fate:type_to_scode/1` FInitArgsT = aeb_fate_data:make_typerep([type_to_fcode(Env, T) || T <- ArgsT]), - builtin_to_fcode(state_layout(Env), chain_clone, [{lit, FInitArgsT}|FArgs]) + builtin_to_fcode(state_layout(Env), chain_clone, [{lit, FAnn, FInitArgsT}|FArgs]) end; - {builtin_u, Ann, chain_create, _Ar} -> + {builtin_u, FAnn, chain_create, _Ar} -> case {ArgsT, Type} of {var_args, _} -> fcode_error({var_args_not_set, FunE}); {_, {con, _, Contract}} -> FInitArgsT = aeb_fate_data:make_typerep([type_to_fcode(Env, T) || T <- ArgsT]), - builtin_to_fcode(state_layout(Env), chain_create, [{lit, {contract_code, Contract}}, {lit, FInitArgsT}|FArgs]); + builtin_to_fcode(state_layout(Env), chain_create, [{lit, FAnn, {contract_code, Contract}}, {lit, FAnn, FInitArgsT}|FArgs]); {_, _} -> fcode_error({not_a_contract_type, Type}) end; - {builtin_u, Ann, B, _Ar} -> builtin_to_fcode(state_layout(Env), B, FArgs); - {def_u, Ann, F, _Ar} -> {def, Ann, F, FArgs}; - {remote_u, Ann, RArgsT, RRetT, Ct, RFun} -> {remote, Ann, RArgsT, RRetT, Ct, RFun, FArgs}; + {builtin_u, _, B, _Ar} -> builtin_to_fcode(state_layout(Env), B, FArgs); + {def_u, FAnn, F, _Ar} -> {def, FAnn, F, FArgs}; + {remote_u, FAnn, RArgsT, RRetT, Ct, RFun} -> {remote, FAnn, RArgsT, RRetT, Ct, RFun, FArgs}; FFun -> %% FFun is a closure, with first component the function name and %% second component the environment @@ -1108,8 +1108,8 @@ expr_to_decision_tree(Env, Expr) -> {atom, expr_to_fcode(Env, Expr)}. -spec decision_tree_to_fcode(decision_tree()) -> fexpr(). -decision_tree_to_fcode(false) -> {lit, {bool, false}}; -decision_tree_to_fcode(true) -> {lit, {bool, true}}; +decision_tree_to_fcode(false) -> {lit, [], {bool, false}}; +decision_tree_to_fcode(true) -> {lit, [], {bool, true}}; decision_tree_to_fcode({atom, B}) -> B; decision_tree_to_fcode({'if', A, Then, Else}) -> X = fresh_name(), @@ -1170,7 +1170,7 @@ set_state({tuple, Ls}, Val) -> -spec get_state(state_layout()) -> fexpr(). get_state({reg, R}) -> - {get_state, R}; + {get_state, [], R}; get_state({tuple, Ls}) -> {tuple, [get_state(L) || L <- Ls]}. @@ -1247,12 +1247,12 @@ event_function(_Env = #{event_type := {variant_t, EventCons}}, EventType = {vari Arities = [length(Ts) || Ts <- FCons], Case = fun({Name, Tag, Ixs}) -> {ok, HashValue} = eblake2:blake2b(?HASH_BYTES, list_to_binary(Name)), - Hash = {lit, {bytes, HashValue}}, + Hash = {lit, [], {bytes, HashValue}}, Vars = [ "arg" ++ integer_to_list(I) || I <- lists:seq(1, length(Ixs)) ], IVars = lists:zip(Ixs, Vars), Payload = case [ V || {notindexed, V} <- IVars ] of - [] -> {lit, {string, <<>>}}; + [] -> {lit, [], {string, <<>>}}; [V] -> {var, [], V} end, Indices = [ {var, [], V} || {indexed, V} <- IVars ], @@ -1345,7 +1345,7 @@ lambda_lift_expr(Layout, {remote_u, Ann, ArgsT, RetT, Ct, F}) -> make_closure(FVs, Xs, {remote, Ann, ArgsT, RetT, Ct1, F, Args}); lambda_lift_expr(Layout, Expr) -> case Expr of - {lit, _} -> Expr; + {lit, _, _} -> Expr; nil -> Expr; {var, _, _} -> Expr; {closure, _, _, _} -> Expr; @@ -1360,7 +1360,7 @@ lambda_lift_expr(Layout, Expr) -> {'let', Ann, X, A, B} -> {'let', Ann, X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)}; {funcall, Ann, A, Bs} -> {funcall, Ann, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)}; {set_state, Ann, R, A} -> {set_state, Ann, R, lambda_lift_expr(Layout, A)}; - {get_state, _} -> Expr; + {get_state, _, _} -> Expr; {switch, Ann, S} -> {switch, Ann, lambda_lift_expr(Layout, S)}; {split, Type, X, Alts} -> {split, Type, X, lambda_lift_exprs(Layout, Alts)}; {nosplit, A} -> {nosplit, lambda_lift_expr(Layout, A)}; @@ -1442,7 +1442,7 @@ make_lets(Es, Body) -> make_lets(Es, [], Body). make_lets([], Xs, Body) -> Body(lists:reverse(Xs)); make_lets([{var, _, _} = E | Es], Xs, Body) -> make_lets(Es, [E | Xs], Body); -make_lets([{lit, _} = E | Es], Xs, Body) -> +make_lets([{lit, _, _} = E | Es], Xs, Body) -> make_lets(Es, [E | Xs], Body); make_lets([E | Es], Xs, Body) -> ?make_let(X, E, make_lets(Es, [X | Xs], Body)). @@ -1547,9 +1547,9 @@ simplify(Env, {proj, _, Var = {var, _, _}, I} = Expr) -> E -> E end; -simplify(Env, {switch, _, Split}) -> +simplify(Env, {switch, FAnn, Split}) -> case simpl_switch(Env, [], Split) of - nomatch -> {builtin, abort, [{lit, {string, <<"Incomplete patterns">>}}]}; + nomatch -> {builtin, abort, [{lit, FAnn, {string, <<"Incomplete patterns">>}}]}; Expr -> Expr end; @@ -1625,7 +1625,7 @@ simpl_case(Env, E, [{'case', Pat, Body} | Alts]) -> -spec match_pat(fsplit_pat(), fexpr()) -> false | [{var_name(), fexpr()}]. match_pat({tuple, Xs}, {tuple, Es}) -> lists:zip(Xs, Es); match_pat({con, _, C, Xs}, {con, _, C, Es}) -> lists:zip(Xs, Es); -match_pat(L, {lit, L}) -> []; +match_pat(L, {lit, _, L}) -> []; match_pat(nil, nil) -> []; match_pat({'::', X, Y}, {op, _, '::', [A, B]}) -> [{X, A}, {Y, B}]; match_pat({var, _, X}, E) -> [{X, E}]; @@ -1652,7 +1652,7 @@ constructor_form(Env, Expr) -> end; {con, _, _, _} -> Expr; {tuple, _} -> Expr; - {lit, _} -> Expr; + {lit, _, _} -> Expr; nil -> Expr; {op, _, '::', _} -> Expr; _ -> false @@ -1675,14 +1675,14 @@ drop_unused_lets(_, Expr) -> Expr. %% -- Static analysis -------------------------------------------------------- -spec safe_to_duplicate(fexpr()) -> boolean(). -safe_to_duplicate({lit, _}) -> true; +safe_to_duplicate({lit, _, _}) -> true; safe_to_duplicate({var, _, _}) -> true; safe_to_duplicate(nil) -> true; safe_to_duplicate({tuple, []}) -> true; safe_to_duplicate(_) -> false. -spec read_only(fexpr() | fsplit() | fcase() | [fexpr()] | [fcase()]) -> boolean(). -read_only({lit, _}) -> true; +read_only({lit, _, _}) -> true; read_only({var, _, _}) -> true; read_only(nil) -> true; read_only({con, _, _, Es}) -> read_only(Es); @@ -1690,7 +1690,7 @@ read_only({tuple, Es}) -> read_only(Es); read_only({proj, _, E, _}) -> read_only(E); read_only({set_proj, _, A, _, B}) -> read_only([A, B]); read_only({op, _, _, Es}) -> read_only(Es); -read_only({get_state, _}) -> true; +read_only({get_state, _, _}) -> true; read_only({set_state, _, _, _}) -> false; read_only({def_u, _, _, _}) -> true; read_only({remote_u, _, _, _, _, _}) -> true; @@ -1931,7 +1931,7 @@ free_vars(Xs) when is_list(Xs) -> free_vars(Expr) -> case Expr of {var, _, X} -> [X]; - {lit, _} -> []; + {lit, _, _} -> []; nil -> []; {def, _, _, As} -> free_vars(As); {def_u, _, _, _} -> []; @@ -1948,7 +1948,7 @@ free_vars(Expr) -> {'let', Ann, X, A, B} -> free_vars([A, {lam, Ann, [X], B}]); {funcall, _, A, Bs} -> free_vars([A | Bs]); {set_state, _, _, A} -> free_vars(A); - {get_state, _} -> []; + {get_state, _, _} -> []; {lam, _, Xs, B} -> free_vars(B) -- lists:sort(Xs); {closure, _, _, A} -> free_vars(A); {switch, _, A} -> free_vars(A); @@ -1963,7 +1963,7 @@ used_defs(Xs) when is_list(Xs) -> used_defs(Expr) -> case Expr of {var, _, _} -> []; - {lit, _} -> []; + {lit, _, _} -> []; nil -> []; {def, _, F, As} -> lists:umerge([F], used_defs(As)); {def_u, _, F, _} -> [F]; @@ -1980,7 +1980,7 @@ used_defs(Expr) -> {'let', _, _, A, B} -> used_defs([A, B]); {funcall, _, A, Bs} -> used_defs([A | Bs]); {set_state, _, _, A} -> used_defs(A); - {get_state, _} -> []; + {get_state, _, _} -> []; {lam, _, _, B} -> used_defs(B); {closure, _, F, A} -> lists:umerge([F], used_defs(A)); {switch, _, A} -> used_defs(A); @@ -1997,7 +1997,7 @@ bottom_up(F, Expr) -> bottom_up(F, #{}, Expr). Fun :: fun((expr_env(), fexpr()) -> fexpr()). bottom_up(F, Env, Expr) -> F(Env, case Expr of - {lit, _} -> Expr; + {lit, _, _} -> Expr; nil -> Expr; {var, _, _} -> Expr; {def, Ann, D, Es} -> {def, Ann, D, [bottom_up(F, Env, E) || E <- Es]}; @@ -2014,7 +2014,7 @@ bottom_up(F, Env, Expr) -> {op, Ann, Op, Es} -> {op, Ann, Op, [bottom_up(F, Env, E) || E <- Es]}; {funcall, Ann, Fun, Es} -> {funcall, Ann, bottom_up(F, Env, Fun), [bottom_up(F, Env, E) || E <- Es]}; {set_state, Ann, R, E} -> {set_state, Ann, R, bottom_up(F, Env, E)}; - {get_state, _} -> Expr; + {get_state, _, _} -> Expr; {closure, Ann, F, CEnv} -> {closure, Ann, F, bottom_up(F, Env, CEnv)}; {switch, Ann, Split} -> {switch, Ann, bottom_up(F, Env, Split)}; {lam, Ann, Xs, B} -> {lam, Ann, Xs, bottom_up(F, Env, B)}; @@ -2057,7 +2057,7 @@ get_named_arg({named_arg_t, _, {id, _, Name}, _, Default}, Args) -> -spec rename(rename(), fexpr()) -> fexpr(). rename(Ren, Expr) -> case Expr of - {lit, _} -> Expr; + {lit, _, _} -> Expr; nil -> nil; {var, Ann, X} -> {var, Ann, rename_var(Ren, X)}; {def, Ann, D, Es} -> {def, Ann, D, [rename(Ren, E) || E <- Es]}; @@ -2074,7 +2074,7 @@ rename(Ren, Expr) -> {op, Ann, Op, Es} -> {op, Ann, Op, [rename(Ren, E) || E <- Es]}; {funcall, Ann, Fun, Es} -> {funcall, Ann, rename(Ren, Fun), [rename(Ren, E) || E <- Es]}; {set_state, Ann, R, E} -> {set_state, Ann, R, rename(Ren, E)}; - {get_state, _} -> Expr; + {get_state, _, _} -> Expr; {closure, Ann, F, Env} -> {closure, Ann, F, rename(Ren, Env)}; {switch, Ann, Split} -> {switch, Ann, rename_split(Ren, Split)}; {lam, Ann, Xs, B} -> @@ -2288,9 +2288,9 @@ pp_par([]) -> prettypr:empty(); pp_par(Xs) -> prettypr:par(Xs). -spec pp_fexpr(fexpr()) -> prettypr:document(). -pp_fexpr({lit, {typerep, T}}) -> +pp_fexpr({lit, _, {typerep, T}}) -> pp_ftype(T); -pp_fexpr({lit, {Tag, Lit}}) -> +pp_fexpr({lit, _, {Tag, Lit}}) -> aeso_pretty:expr({Tag, [], Lit}); pp_fexpr(nil) -> pp_text("[]"); @@ -2356,10 +2356,10 @@ pp_fexpr({remote, _, ArgsT, RetT, Ct, Fun, As}) -> pp_call(pp_parens(pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun), pp_text(" : "), pp_ftype({function, ArgsT, RetT})])), As); pp_fexpr({funcall, _, Fun, As}) -> pp_call(pp_fexpr(Fun), As); -pp_fexpr({set_state, _, R, A}) -> - pp_call(pp_text("set_state"), [{lit, {int, R}}, A]); -pp_fexpr({get_state, R}) -> - pp_call(pp_text("get_state"), [{lit, {int, R}}]); +pp_fexpr({set_state, FAnn, R, A}) -> + pp_call(pp_text("set_state"), [{lit, FAnn, {int, R}}, A]); +pp_fexpr({get_state, FAnn, R}) -> + pp_call(pp_text("get_state"), [{lit, FAnn, {int, R}}]); pp_fexpr({switch, _, Split}) -> pp_split(Split); pp_fexpr({contract_code, Contract}) -> pp_beside(pp_text("contract "), pp_text(Contract)). @@ -2376,7 +2376,7 @@ pp_call_t(Fun, Args) -> pp_ftype(T) when is_atom(T) -> pp_text(T); pp_ftype(any) -> pp_text("_"); pp_ftype({tvar, X}) -> pp_text(X); -pp_ftype({bytes, N}) -> pp_call(pp_text("bytes"), [{lit, {int, N}}]); +pp_ftype({bytes, N}) -> pp_call(pp_text("bytes"), [{lit, [], {int, N}}]); pp_ftype({oracle, Q, R}) -> pp_call_t("oracle", [Q, R]); pp_ftype({tuple, Ts}) -> pp_parens(pp_par(pp_punctuate(pp_text(" *"), [pp_ftype(T) || T <- Ts]))); @@ -2411,7 +2411,7 @@ pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, [], X}, {var, [], Xs} pp_pat({con, As, I, Xs}) -> pp_fexpr({con, As, I, [{var, [], X} || X <- Xs]}); pp_pat({var, Ann, X}) -> pp_fexpr({var, Ann, X}); pp_pat(P = {Tag, _}) when Tag == bool; Tag == int; Tag == string - -> pp_fexpr({lit, P}); + -> pp_fexpr({lit, [], P}); pp_pat(Pat) -> pp_fexpr(Pat). -spec is_infix(op()) -> boolean(). -- 2.30.2 From 9f082b1af28908f05bb2078f44824effc9e89ab9 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 9 Nov 2022 14:31:20 +0300 Subject: [PATCH 20/92] Add fann() to builtin --- src/aeso_ast_to_fcode.erl | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index d94d5fd..532d1ba 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -65,7 +65,7 @@ | {var, fann(), var_name()} | {def, fann(), fun_name(), [fexpr()]} | {remote, fann(), [ftype()], ftype(), fexpr(), fun_name(), [fexpr()]} - | {builtin, builtin(), [fexpr()]} + | {builtin, fann(), builtin(), [fexpr()]} | {con, arities(), tag(), [fexpr()]} | {tuple, [fexpr()]} | {proj, fann(), fexpr(), integer()} @@ -771,8 +771,8 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A end; %% Maps -expr_to_fcode(_Env, _Type, {map, _, []}) -> - {builtin, map_empty, []}; +expr_to_fcode(_Env, _Type, {map, Ann, []}) -> + {builtin, to_fann(Ann), map_empty, []}; expr_to_fcode(Env, Type, {map, Ann, KVs}) -> %% Cheaper to do incremental map_update than building the list and doing %% map_from_list (I think). @@ -1181,7 +1181,7 @@ builtin_to_fcode(Layout, set_state, [Val]) -> builtin_to_fcode(Layout, get_state, []) -> get_state(Layout); builtin_to_fcode(_Layout, require, [Cond, Msg]) -> - make_if(Cond, {tuple, []}, {builtin, abort, [Msg]}); + make_if(Cond, {tuple, []}, {builtin, get_fann(Cond), abort, [Msg]}); builtin_to_fcode(_Layout, chain_event, [Event]) -> {def, [], event, [Event]}; builtin_to_fcode(_Layout, map_delete, [Key, Map]) -> @@ -1203,7 +1203,7 @@ builtin_to_fcode(_Layout, Builtin, Args) -> end, case lists:member(Builtin, op_builtins()) of true -> {op, FAnn, Builtin, Args}; - false -> {builtin, Builtin, Args} + false -> {builtin, FAnn, Builtin, Args} end. %% -- Init function -- @@ -1256,7 +1256,7 @@ event_function(_Env = #{event_type := {variant_t, EventCons}}, EventType = {vari [V] -> {var, [], V} end, Indices = [ {var, [], V} || {indexed, V} <- IVars ], - Body = {builtin, chain_event, [Payload, Hash | Indices]}, + Body = {builtin, [], chain_event, [Payload, Hash | Indices]}, {'case', {con, Arities, Tag, Vars}, {nosplit, Body}} end, #{ attrs => [private], @@ -1350,7 +1350,7 @@ lambda_lift_expr(Layout, Expr) -> {var, _, _} -> Expr; {closure, _, _, _} -> Expr; {def, Ann, D, As} -> {def, Ann, D, lambda_lift_exprs(Layout, As)}; - {builtin, B, As} -> {builtin, B, lambda_lift_exprs(Layout, As)}; + {builtin, Ann, B, As} -> {builtin, Ann, B, lambda_lift_exprs(Layout, As)}; {remote, Ann, ArgsT, RetT, Ct, F, As} -> {remote, Ann, ArgsT, RetT, lambda_lift_expr(Layout, Ct), F, lambda_lift_exprs(Layout, As)}; {con, Ar, C, As} -> {con, Ar, C, lambda_lift_exprs(Layout, As)}; {tuple, As} -> {tuple, lambda_lift_exprs(Layout, As)}; @@ -1549,7 +1549,7 @@ simplify(Env, {proj, _, Var = {var, _, _}, I} = Expr) -> simplify(Env, {switch, FAnn, Split}) -> case simpl_switch(Env, [], Split) of - nomatch -> {builtin, abort, [{lit, FAnn, {string, <<"Incomplete patterns">>}}]}; + nomatch -> {builtin, FAnn, abort, [{lit, FAnn, {string, <<"Incomplete patterns">>}}]}; Expr -> Expr end; @@ -1699,7 +1699,7 @@ read_only({builtin_u, _, _, _, _}) -> true; read_only({lam, _, _, _}) -> true; read_only({def, _, _, _}) -> false; %% TODO: purity analysis read_only({remote, _, _, _, _, _, _}) -> false; -read_only({builtin, _, _}) -> false; %% TODO: some builtins are +read_only({builtin, _, _, _}) -> false; %% TODO: some builtins are read_only({switch, _, Split}) -> read_only(Split); read_only({split, _, _, Cases}) -> read_only(Cases); read_only({nosplit, E}) -> read_only(E); @@ -1937,7 +1937,7 @@ free_vars(Expr) -> {def_u, _, _, _} -> []; {remote, _, _, _, Ct, _, As} -> free_vars([Ct | As]); {remote_u, _, _, _, Ct, _} -> free_vars(Ct); - {builtin, _, As} -> free_vars(As); + {builtin, _, _, As} -> free_vars(As); {builtin_u, _, _, _} -> []; {builtin_u, _, _, _, _} -> []; %% Typereps are always literals {con, _, _, As} -> free_vars(As); @@ -1969,7 +1969,7 @@ used_defs(Expr) -> {def_u, _, F, _} -> [F]; {remote, _, _, _, Ct, _, As} -> used_defs([Ct | As]); {remote_u, _, _, _, Ct, _} -> used_defs(Ct); - {builtin, _, As} -> used_defs(As); + {builtin, _, _, As} -> used_defs(As); {builtin_u, _, _, _} -> []; {builtin_u, _, _, _, _} -> []; {con, _, _, As} -> used_defs(As); @@ -2002,7 +2002,7 @@ bottom_up(F, Env, Expr) -> {var, _, _} -> Expr; {def, Ann, D, Es} -> {def, Ann, D, [bottom_up(F, Env, E) || E <- Es]}; {def_u, _, _, _} -> Expr; - {builtin, B, Es} -> {builtin, B, [bottom_up(F, Env, E) || E <- Es]}; + {builtin, Ann, B, Es} -> {builtin, Ann, B, [bottom_up(F, Env, E) || E <- Es]}; {builtin_u, _, _, _} -> Expr; {builtin_u, _, _, _, _} -> Expr; {remote, Ann, ArgsT, RetT, Ct, Fun, Es} -> {remote, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun, [bottom_up(F, Env, E) || E <- Es]}; @@ -2062,7 +2062,7 @@ rename(Ren, Expr) -> {var, Ann, X} -> {var, Ann, rename_var(Ren, X)}; {def, Ann, D, Es} -> {def, Ann, D, [rename(Ren, E) || E <- Es]}; {def_u, _, _, _} -> Expr; - {builtin, B, Es} -> {builtin, B, [rename(Ren, E) || E <- Es]}; + {builtin, Ann, B, Es} -> {builtin, Ann, B, [rename(Ren, E) || E <- Es]}; {builtin_u, _, _, _} -> Expr; {builtin_u, _, _, _, _} -> Expr; {remote, Ann, ArgsT, RetT, Ct, F, Es} -> {remote, Ann, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; @@ -2348,7 +2348,7 @@ pp_fexpr({builtin_u, _, B, N}) -> pp_beside([pp_text(B), pp_text("/"), pp_text(N)]); pp_fexpr({builtin_u, _, B, N, TypeArgs}) -> pp_beside([pp_text(B), pp_text("@"), pp_fexpr({tuple, TypeArgs}), pp_text("/"), pp_text(N)]); -pp_fexpr({builtin, B, As}) -> +pp_fexpr({builtin, _, B, As}) -> pp_call(pp_text(B), As); pp_fexpr({remote_u, _, ArgsT, RetT, Ct, Fun}) -> pp_beside([pp_fexpr(Ct), pp_text("."), pp_fun_name(Fun), pp_text(" : "), pp_ftype({function, ArgsT, RetT})]); -- 2.30.2 From 0611bcae9ddbb4986e1335b420251fca9a22c1a4 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 9 Nov 2022 15:06:16 +0300 Subject: [PATCH 21/92] Add fann() to con --- src/aeso_ast_to_fcode.erl | 148 +++++++++++++++++++------------------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 532d1ba..49dee46 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -66,7 +66,7 @@ | {def, fann(), fun_name(), [fexpr()]} | {remote, fann(), [ftype()], ftype(), fexpr(), fun_name(), [fexpr()]} | {builtin, fann(), builtin(), [fexpr()]} - | {con, arities(), tag(), [fexpr()]} + | {con, fann(), arities(), tag(), [fexpr()]} | {tuple, [fexpr()]} | {proj, fann(), fexpr(), integer()} | {set_proj, fann(), fexpr(), integer(), fexpr()} %% tuple, field, new_value @@ -97,7 +97,7 @@ | {string, binary()} | nil | {'::', var_name(), var_name()} - | {con, arities(), tag(), [var_name()]} + | {con, fann(), arities(), tag(), [var_name()]} | {tuple, [var_name()]} | {assign, var_name(), var_name()}. @@ -599,11 +599,11 @@ expr_to_fcode(Env, Type, {qid, _, X}) -> %% Constructors expr_to_fcode(Env, Type, {C, _, _} = Con) when C == con; C == qcon -> expr_to_fcode(Env, Type, {app, [], {typed, [], Con, Type}, []}); -expr_to_fcode(Env, _Type, {app, _, {typed, _, {C, _, _} = Con, _}, Args}) when C == con; C == qcon -> +expr_to_fcode(Env, _Type, {app, _, {typed, _, {C, Ann, _} = Con, _}, Args}) when C == con; C == qcon -> #con_tag{ tag = I, arities = Arities } = lookup_con(Env, Con), Arity = lists:nth(I + 1, Arities), case length(Args) == Arity of - true -> {con, Arities, I, [expr_to_fcode(Env, Arg) || Arg <- Args]}; + true -> {con, to_fann(Ann), Arities, I, [expr_to_fcode(Env, Arg) || Arg <- Args]}; false -> internal_error({constructor_arity_mismatch, Con, length(Args), Arity}) end; @@ -868,7 +868,7 @@ alts_to_fcode(Env, Type, X, Alts, Switch) -> | nil | {'::', fpat(), fpat()} | {tuple, [fpat()]} - | {con, arities(), tag(), [fpat()]} + | {con, fann(), arities(), tag(), [fpat()]} | {assign, fpat(), fpat()}. -spec remove_guards(env(), [aeso_syntax:alt()], aeso_syntax:expr()) -> [falt()]. @@ -945,18 +945,18 @@ merge_alts(I, X, Alts, Alts1) -> when Alts :: [{fsplit_pat(), [falt()]}]. merge_alt(_, _, {P, A}, []) -> [{P, [A]}]; merge_alt(I, X, {P, A}, [{Q, As} | Rest]) -> - Match = fun({var, _, _}, {var, _, _}) -> match; - ({tuple, _}, {tuple, _}) -> match; - ({bool, B}, {bool, B}) -> match; - ({int, N}, {int, N}) -> match; - ({string, S}, {string, S}) -> match; - (nil, nil) -> match; - ({'::', _, _}, {'::', _, _}) -> match; - ({con, _, C, _}, {con, _, C, _}) -> match; - ({con, _, _, _}, {con, _, _, _}) -> mismatch; - ({var, _, _}, _) -> expand; - (_, {var, _, _}) -> insert; - (_, _) -> mismatch + Match = fun({var, _, _}, {var, _, _}) -> match; + ({tuple, _}, {tuple, _}) -> match; + ({bool, B}, {bool, B}) -> match; + ({int, N}, {int, N}) -> match; + ({string, S}, {string, S}) -> match; + (nil, nil) -> match; + ({'::', _, _}, {'::', _, _}) -> match; + ({con, _, _, C, _}, {con, _, _, C, _}) -> match; + ({con, _, _, _, _}, {con, _, _, _, _}) -> mismatch; + ({var, _, _}, _) -> expand; + (_, {var, _, _}) -> insert; + (_, _) -> mismatch end, case Match(P, Q) of match -> [{Q, [A | As]} | Rest]; @@ -974,13 +974,13 @@ expand(I, X, P, Q, Case = {'case', Ps, E}) -> {Ps1r, Ren2} = rename_fpats(Ren1, Ps1), E1 = rename(Ren2, E), Splice = fun(N) -> Ps0r ++ lists:duplicate(N, {var, [], "_"}) ++ Ps1r end, - Type = fun({tuple, Xs}) -> {tuple, length(Xs)}; - ({bool, _}) -> bool; - ({int, _}) -> int; - ({string, _}) -> string; - (nil) -> list; - ({'::', _, _}) -> list; - ({con, As, _, _}) -> {variant, As} + Type = fun({tuple, Xs}) -> {tuple, length(Xs)}; + ({bool, _}) -> bool; + ({int, _}) -> int; + ({string, _}) -> string; + (nil) -> list; + ({'::', _, _}) -> list; + ({con, _, As, _, _}) -> {variant, As} end, MkCase = fun(Pat, Vars) -> {Pat, {'case', Splice(Vars), E1}} end, case Type(Q) of @@ -989,7 +989,7 @@ expand(I, X, P, Q, Case = {'case', Ps, E}) -> int -> {[MkCase(Q, 0)], [{P, Case}]}; string -> {[MkCase(Q, 0)], [{P, Case}]}; list -> {[MkCase(nil, 0), MkCase({'::', fresh_name(), fresh_name()}, 2)], []}; - {variant, As} -> {[MkCase({con, As, C - 1, [fresh_name() || _ <- lists:seq(1, Ar)]}, Ar) + {variant, As} -> {[MkCase({con, [], As, C - 1, [fresh_name() || _ <- lists:seq(1, Ar)]}, Ar) || {C, Ar} <- indexed(As)], []} end. @@ -1006,9 +1006,9 @@ split_pat({int, N}) -> {{int, N}, []}; split_pat({string, N}) -> {{string, N}, []}; split_pat(nil) -> {nil, []}; split_pat({'::', P, Q}) -> {{'::', fresh_name(), fresh_name()}, [P, Q]}; -split_pat({con, As, I, Pats}) -> +split_pat({con, FAnn, As, I, Pats}) -> Xs = [fresh_name() || _ <- Pats], - {{con, As, I, Xs}, Pats}; + {{con, FAnn, As, I, Xs}, Pats}; split_pat({assign, X = {var, _, _}, P}) -> {{assign, fresh_name(), fresh_name()}, [X, P]}; split_pat({tuple, Pats}) -> @@ -1022,7 +1022,7 @@ split_vars({string, _}, string) -> []; split_vars(nil, {list, _}) -> []; split_vars({'::', X, Xs}, {list, T}) -> [{X, T}, {Xs, {list, T}}]; split_vars({assign, X, P}, T) -> [{X, T}, {P, T}]; -split_vars({con, _, I, Xs}, {variant, Cons}) -> +split_vars({con, _, _, I, Xs}, {variant, Cons}) -> lists:zip(Xs, lists:nth(I + 1, Cons)); split_vars({tuple, Xs}, {tuple, Ts}) -> lists:zip(Xs, Ts); @@ -1050,12 +1050,12 @@ pat_to_fcode(Env, Pat) -> -spec pat_to_fcode(env(), aeso_syntax:type() | no_type, aeso_syntax:pat()) -> fpat(). pat_to_fcode(_Env, _Type, {id, Ann, X}) -> {var, to_fann(Ann), X}; -pat_to_fcode(Env, _Type, {C, _, _} = Con) when C == con; C == qcon -> +pat_to_fcode(Env, _Type, {C, Ann, _} = Con) when C == con; C == qcon -> #con_tag{tag = I, arities = As} = lookup_con(Env, Con), - {con, As, I, []}; -pat_to_fcode(Env, _Type, {app, _, {typed, _, {C, _, _} = Con, _}, Pats}) when C == con; C == qcon -> + {con, to_fann(Ann), As, I, []}; +pat_to_fcode(Env, _Type, {app, _, {typed, _, {C, Ann, _} = Con, _}, Pats}) when C == con; C == qcon -> #con_tag{tag = I, arities = As} = lookup_con(Env, Con), - {con, As, I, [pat_to_fcode(Env, Pat) || Pat <- Pats]}; + {con, to_fann(Ann), As, I, [pat_to_fcode(Env, Pat) || Pat <- Pats]}; pat_to_fcode(Env, _Type, {tuple, _, Pats}) -> make_tuple([ pat_to_fcode(Env, Pat) || Pat <- Pats ]); pat_to_fcode(_Env, _Type, {bool, _, B}) -> {bool, B}; @@ -1192,8 +1192,8 @@ builtin_to_fcode(_Layout, map_lookup, [Key0, Map0]) -> ?make_let(Key, Key0, ?make_let(Map, Map0, make_if({op, get_fann(Map), map_member, [Map, Key]}, - {con, [0, 1], 1, [{op, get_fann(Map), map_get, [Map, Key]}]}, - {con, [0, 1], 0, []}))); + {con, get_fann(Map), [0, 1], 1, [{op, get_fann(Map), map_get, [Map, Key]}]}, + {con, get_fann(Map), [0, 1], 0, []}))); builtin_to_fcode(_Layout, map_lookup_default, [Key, Map, Def]) -> {op, get_fann(Map), map_get_d, [Map, Key, Def]}; builtin_to_fcode(_Layout, Builtin, Args) -> @@ -1257,7 +1257,7 @@ event_function(_Env = #{event_type := {variant_t, EventCons}}, EventType = {vari end, Indices = [ {var, [], V} || {indexed, V} <- IVars ], Body = {builtin, [], chain_event, [Payload, Hash | Indices]}, - {'case', {con, Arities, Tag, Vars}, {nosplit, Body}} + {'case', {con, [], Arities, Tag, Vars}, {nosplit, Body}} end, #{ attrs => [private], args => [{"e", EventType}], @@ -1352,7 +1352,7 @@ lambda_lift_expr(Layout, Expr) -> {def, Ann, D, As} -> {def, Ann, D, lambda_lift_exprs(Layout, As)}; {builtin, Ann, B, As} -> {builtin, Ann, B, lambda_lift_exprs(Layout, As)}; {remote, Ann, ArgsT, RetT, Ct, F, As} -> {remote, Ann, ArgsT, RetT, lambda_lift_expr(Layout, Ct), F, lambda_lift_exprs(Layout, As)}; - {con, Ar, C, As} -> {con, Ar, C, lambda_lift_exprs(Layout, As)}; + {con, Ann, Ar, C, As} -> {con, Ann, Ar, C, lambda_lift_exprs(Layout, As)}; {tuple, As} -> {tuple, lambda_lift_exprs(Layout, As)}; {proj, Ann, A, I} -> {proj, Ann, lambda_lift_expr(Layout, A), I}; {set_proj, Ann, A, I, B} -> {set_proj, Ann, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)}; @@ -1623,14 +1623,14 @@ simpl_case(Env, E, [{'case', Pat, Body} | Alts]) -> end. -spec match_pat(fsplit_pat(), fexpr()) -> false | [{var_name(), fexpr()}]. -match_pat({tuple, Xs}, {tuple, Es}) -> lists:zip(Xs, Es); -match_pat({con, _, C, Xs}, {con, _, C, Es}) -> lists:zip(Xs, Es); -match_pat(L, {lit, _, L}) -> []; -match_pat(nil, nil) -> []; -match_pat({'::', X, Y}, {op, _, '::', [A, B]}) -> [{X, A}, {Y, B}]; -match_pat({var, _, X}, E) -> [{X, E}]; -match_pat({assign, X, P}, E) -> [{X, E}, {P, E}]; -match_pat(_, _) -> false. +match_pat({tuple, Xs}, {tuple, Es}) -> lists:zip(Xs, Es); +match_pat({con, _, _, C, Xs}, {con, _, _, C, Es}) -> lists:zip(Xs, Es); +match_pat(L, {lit, _, L}) -> []; +match_pat(nil, nil) -> []; +match_pat({'::', X, Y}, {op, _, '::', [A, B]}) -> [{X, A}, {Y, B}]; +match_pat({var, _, X}, E) -> [{X, E}]; +match_pat({assign, X, P}, E) -> [{X, E}, {P, E}]; +match_pat(_, _) -> false. -spec constructor_form(expr_env(), fexpr()) -> fexpr() | false. constructor_form(Env, Expr) -> @@ -1650,7 +1650,7 @@ constructor_form(Env, Expr) -> {tuple, Es} -> constructor_form(Env, lists:nth(I + 1, Es)); _ -> false end; - {con, _, _, _} -> Expr; + {con, _, _, _, _} -> Expr; {tuple, _} -> Expr; {lit, _, _} -> Expr; nil -> Expr; @@ -1685,7 +1685,7 @@ safe_to_duplicate(_) -> false. read_only({lit, _, _}) -> true; read_only({var, _, _}) -> true; read_only(nil) -> true; -read_only({con, _, _, Es}) -> read_only(Es); +read_only({con, _, _, _, Es}) -> read_only(Es); read_only({tuple, Es}) -> read_only(Es); read_only({proj, _, E, _}) -> read_only(E); read_only({set_proj, _, A, _, B}) -> read_only([A, B]); @@ -1911,19 +1911,19 @@ pat_vars({string, _}) -> []; pat_vars(nil) -> []; pat_vars({'::', P, Q}) -> pat_vars(P) ++ pat_vars(Q); pat_vars({tuple, Ps}) -> pat_vars(Ps); -pat_vars({con, _, _, Ps}) -> pat_vars(Ps); +pat_vars({con, _, _, _, Ps}) -> pat_vars(Ps); pat_vars({assign, X, P}) -> pat_vars(X) ++ pat_vars(P); pat_vars(Ps) when is_list(Ps) -> [X || P <- Ps, X <- pat_vars(P)]. -spec fsplit_pat_vars(fsplit_pat()) -> [var_name()]. -fsplit_pat_vars({var, _, X}) -> [X || X /= "_"]; -fsplit_pat_vars({bool, _}) -> []; -fsplit_pat_vars({int, _}) -> []; -fsplit_pat_vars({string, _}) -> []; -fsplit_pat_vars(nil) -> []; -fsplit_pat_vars({'::', P, Q}) -> [P, Q]; -fsplit_pat_vars({tuple, Ps}) -> Ps; -fsplit_pat_vars({con, _, _, Ps}) -> Ps. +fsplit_pat_vars({var, _, X}) -> [X || X /= "_"]; +fsplit_pat_vars({bool, _}) -> []; +fsplit_pat_vars({int, _}) -> []; +fsplit_pat_vars({string, _}) -> []; +fsplit_pat_vars(nil) -> []; +fsplit_pat_vars({'::', P, Q}) -> [P, Q]; +fsplit_pat_vars({tuple, Ps}) -> Ps; +fsplit_pat_vars({con, _, _, _, Ps}) -> Ps. -spec free_vars(fexpr() | [fexpr()]) -> [var_name()]. free_vars(Xs) when is_list(Xs) -> @@ -1940,7 +1940,7 @@ free_vars(Expr) -> {builtin, _, _, As} -> free_vars(As); {builtin_u, _, _, _} -> []; {builtin_u, _, _, _, _} -> []; %% Typereps are always literals - {con, _, _, As} -> free_vars(As); + {con, _, _, _, As} -> free_vars(As); {tuple, As} -> free_vars(As); {proj, _, A, _} -> free_vars(A); {set_proj, _, A, _, B} -> free_vars([A, B]); @@ -1972,7 +1972,7 @@ used_defs(Expr) -> {builtin, _, _, As} -> used_defs(As); {builtin_u, _, _, _} -> []; {builtin_u, _, _, _, _} -> []; - {con, _, _, As} -> used_defs(As); + {con, _, _, _, As} -> used_defs(As); {tuple, As} -> used_defs(As); {proj, _, A, _} -> used_defs(A); {set_proj, _, A, _, B} -> used_defs([A, B]); @@ -2007,7 +2007,7 @@ bottom_up(F, Env, Expr) -> {builtin_u, _, _, _, _} -> Expr; {remote, Ann, ArgsT, RetT, Ct, Fun, Es} -> {remote, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun, [bottom_up(F, Env, E) || E <- Es]}; {remote_u, Ann, ArgsT, RetT, Ct, Fun} -> {remote_u, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun}; - {con, Ar, I, Es} -> {con, Ar, I, [bottom_up(F, Env, E) || E <- Es]}; + {con, Ann, Ar, I, Es} -> {con, Ann, Ar, I, [bottom_up(F, Env, E) || E <- Es]}; {tuple, Es} -> {tuple, [bottom_up(F, Env, E) || E <- Es]}; {proj, Ann, E, I} -> {proj, Ann, bottom_up(F, Env, E), I}; {set_proj, Ann, R, I, E} -> {set_proj, Ann, bottom_up(F, Env, R), I, bottom_up(F, Env, E)}; @@ -2067,7 +2067,7 @@ rename(Ren, Expr) -> {builtin_u, _, _, _, _} -> Expr; {remote, Ann, ArgsT, RetT, Ct, F, Es} -> {remote, Ann, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; {remote_u, Ann, ArgsT, RetT, Ct, F} -> {remote_u, Ann, ArgsT, RetT, rename(Ren, Ct), F}; - {con, Ar, I, Es} -> {con, Ar, I, [rename(Ren, E) || E <- Es]}; + {con, Ann, Ar, I, Es} -> {con, Ann, Ar, I, [rename(Ren, E) || E <- Es]}; {tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]}; {proj, Ann, E, I} -> {proj, Ann, rename(Ren, E), I}; {set_proj, Ann, R, I, E} -> {set_proj, Ann, rename(Ren, R), I, rename(Ren, E)}; @@ -2124,9 +2124,9 @@ rename_fpat(Ren, {'::', P, Q}) -> rename_fpat(Ren, {var, Ann, X}) -> {Z, Ren1} = rename_binding(Ren, X), {{var, Ann, Z}, Ren1}; -rename_fpat(Ren, {con, Ar, C, Ps}) -> +rename_fpat(Ren, {con, Ann, Ar, C, Ps}) -> {Ps1, Ren1} = rename_fpats(Ren, Ps), - {{con, Ar, C, Ps1}, Ren1}; + {{con, Ann, Ar, C, Ps1}, Ren1}; rename_fpat(Ren, {tuple, Ps}) -> {Ps1, Ren1} = rename_fpats(Ren, Ps), {{tuple, Ps1}, Ren1}. @@ -2143,9 +2143,9 @@ rename_spat(Ren, {'::', X, Y}) -> rename_spat(Ren, {var, Ann, X}) -> {Z, Ren1} = rename_binding(Ren, X), {{var, Ann, Z}, Ren1}; -rename_spat(Ren, {con, Ar, C, Xs}) -> +rename_spat(Ren, {con, Ann, Ar, C, Xs}) -> {Zs, Ren1} = rename_bindings(Ren, Xs), - {{con, Ar, C, Zs}, Ren1}; + {{con, Ann, Ar, C, Zs}, Ren1}; rename_spat(Ren, {tuple, Xs}) -> {Zs, Ren1} = rename_bindings(Ren, Xs), {{tuple, Zs}, Ren1}; @@ -2300,10 +2300,10 @@ pp_fexpr({def_u, _, Fun, Ar}) -> pp_beside([pp_fun_name(Fun), pp_text("/"), pp_int(Ar)]); pp_fexpr({def, _, Fun, Args}) -> pp_call(pp_fun_name(Fun), Args); -pp_fexpr({con, _, I, []}) -> +pp_fexpr({con, _, _, I, []}) -> pp_beside(pp_text("C"), pp_int(I)); -pp_fexpr({con, _, I, Es}) -> - pp_beside(pp_fexpr({con, [], I, []}), +pp_fexpr({con, Ann, _, I, Es}) -> + pp_beside(pp_fexpr({con, Ann, [], I, []}), pp_fexpr({tuple, Es})); pp_fexpr({tuple, Es}) -> pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_fexpr(E) || E <- Es]))); @@ -2390,8 +2390,8 @@ pp_ftype({variant, Cons}) -> pp_par( pp_punctuate(pp_text(" |"), [ case Args of - [] -> pp_fexpr({con, [], I - 1, []}); - _ -> pp_beside(pp_fexpr({con, [], I - 1, []}), pp_ftype({tuple, Args})) + [] -> pp_fexpr({con, [], [], I - 1, []}); + _ -> pp_beside(pp_fexpr({con, [], [], I - 1, []}), pp_ftype({tuple, Args})) end || {I, Args} <- indexed(Cons)])). -spec pp_split(fsplit()) -> prettypr:document(). @@ -2406,13 +2406,13 @@ pp_case({'case', Pat, Split}) -> prettypr:nest(2, pp_split(Split))]). -spec pp_pat(fsplit_pat()) -> prettypr:document(). -pp_pat({tuple, Xs}) -> pp_fexpr({tuple, [{var, [], X} || X <- Xs]}); -pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, [], X}, {var, [], Xs}]}); -pp_pat({con, As, I, Xs}) -> pp_fexpr({con, As, I, [{var, [], X} || X <- Xs]}); -pp_pat({var, Ann, X}) -> pp_fexpr({var, Ann, X}); +pp_pat({tuple, Xs}) -> pp_fexpr({tuple, [{var, [], X} || X <- Xs]}); +pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, [], X}, {var, [], Xs}]}); +pp_pat({con, Ann, As, I, Xs}) -> pp_fexpr({con, Ann, As, I, [{var, [], X} || X <- Xs]}); +pp_pat({var, Ann, X}) -> pp_fexpr({var, Ann, X}); pp_pat(P = {Tag, _}) when Tag == bool; Tag == int; Tag == string - -> pp_fexpr({lit, [], P}); -pp_pat(Pat) -> pp_fexpr(Pat). + -> pp_fexpr({lit, [], P}); +pp_pat(Pat) -> pp_fexpr(Pat). -spec is_infix(op()) -> boolean(). is_infix(Op) -> -- 2.30.2 From 76487328798cd3fee19e9c0f81090a5ef11af694 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 9 Nov 2022 17:08:14 +0300 Subject: [PATCH 22/92] Add fann() to tuple --- src/aeso_ast_to_fcode.erl | 110 +++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 49dee46..1277e3d 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -67,7 +67,7 @@ | {remote, fann(), [ftype()], ftype(), fexpr(), fun_name(), [fexpr()]} | {builtin, fann(), builtin(), [fexpr()]} | {con, fann(), arities(), tag(), [fexpr()]} - | {tuple, [fexpr()]} + | {tuple, fann(), [fexpr()]} | {proj, fann(), fexpr(), integer()} | {set_proj, fann(), fexpr(), integer(), fexpr()} %% tuple, field, new_value | {op, fann(), op(), [fexpr()]} @@ -98,7 +98,7 @@ | nil | {'::', var_name(), var_name()} | {con, fann(), arities(), tag(), [var_name()]} - | {tuple, [var_name()]} + | {tuple, fann(), [var_name()]} | {assign, var_name(), var_name()}. -type ftype() :: integer @@ -659,7 +659,7 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) -> Expand = length(Fields) == length(FieldTypes), Updates = [ {I, field_value(FT, Fields)} || {I, FT} <- indexed(FieldTypes) ], Body = case Expand of - true -> {tuple, lists:map(Comp, Updates)}; + true -> {tuple, [], lists:map(Comp, Updates)}; false -> lists:foldr(Set, {var, FAnn, X}, Updates) end, {'let', FAnn, X, expr_to_fcode(Env, Rec), Body}; @@ -834,10 +834,10 @@ make_if_no_else(Cond, Then) -> -spec make_tuple([fexpr()]) -> fexpr(). make_tuple([E]) -> E; -make_tuple(Es) -> {tuple, Es}. +make_tuple(Es) -> {tuple, [], Es}. -spec strip_singleton_tuples(ftype()) -> ftype(). -strip_singleton_tuples({tuple, [T]}) -> strip_singleton_tuples(T); +strip_singleton_tuples({tuple, _, [T]}) -> strip_singleton_tuples(T); strip_singleton_tuples(T) -> T. -spec get_oracle_type(OracleFun, FunT) -> OracleType when @@ -867,7 +867,7 @@ alts_to_fcode(Env, Type, X, Alts, Switch) -> | {string, binary()} | nil | {'::', fpat(), fpat()} - | {tuple, [fpat()]} + | {tuple, fann(), [fpat()]} | {con, fann(), arities(), tag(), [fpat()]} | {assign, fpat(), fpat()}. @@ -946,7 +946,7 @@ merge_alts(I, X, Alts, Alts1) -> merge_alt(_, _, {P, A}, []) -> [{P, [A]}]; merge_alt(I, X, {P, A}, [{Q, As} | Rest]) -> Match = fun({var, _, _}, {var, _, _}) -> match; - ({tuple, _}, {tuple, _}) -> match; + ({tuple, _, _}, {tuple, _, _}) -> match; ({bool, B}, {bool, B}) -> match; ({int, N}, {int, N}) -> match; ({string, S}, {string, S}) -> match; @@ -974,7 +974,7 @@ expand(I, X, P, Q, Case = {'case', Ps, E}) -> {Ps1r, Ren2} = rename_fpats(Ren1, Ps1), E1 = rename(Ren2, E), Splice = fun(N) -> Ps0r ++ lists:duplicate(N, {var, [], "_"}) ++ Ps1r end, - Type = fun({tuple, Xs}) -> {tuple, length(Xs)}; + Type = fun({tuple, _, Xs}) -> {tuple, length(Xs)}; ({bool, _}) -> bool; ({int, _}) -> int; ({string, _}) -> string; @@ -1011,9 +1011,9 @@ split_pat({con, FAnn, As, I, Pats}) -> {{con, FAnn, As, I, Xs}, Pats}; split_pat({assign, X = {var, _, _}, P}) -> {{assign, fresh_name(), fresh_name()}, [X, P]}; -split_pat({tuple, Pats}) -> +split_pat({tuple, FAnn, Pats}) -> Xs = [fresh_name() || _ <- Pats], - {{tuple, Xs}, Pats}. + {{tuple, FAnn, Xs}, Pats}. -spec split_vars(fsplit_pat(), ftype()) -> [{var_name(), ftype()}]. split_vars({bool, _}, boolean) -> []; @@ -1024,7 +1024,7 @@ split_vars({'::', X, Xs}, {list, T}) -> [{X, T}, {Xs, {list, T}}]; split_vars({assign, X, P}, T) -> [{X, T}, {P, T}]; split_vars({con, _, _, I, Xs}, {variant, Cons}) -> lists:zip(Xs, lists:nth(I + 1, Cons)); -split_vars({tuple, Xs}, {tuple, Ts}) -> +split_vars({tuple, _, Xs}, {tuple, Ts}) -> lists:zip(Xs, Ts); split_vars({var, _, X}, T) -> [{X, T}]. @@ -1181,7 +1181,7 @@ builtin_to_fcode(Layout, set_state, [Val]) -> builtin_to_fcode(Layout, get_state, []) -> get_state(Layout); builtin_to_fcode(_Layout, require, [Cond, Msg]) -> - make_if(Cond, {tuple, []}, {builtin, get_fann(Cond), abort, [Msg]}); + make_if(Cond, {tuple, get_fann(Cond), []}, {builtin, get_fann(Cond), abort, [Msg]}); builtin_to_fcode(_Layout, chain_event, [Event]) -> {def, [], event, [Event]}; builtin_to_fcode(_Layout, map_delete, [Key, Map]) -> @@ -1229,7 +1229,7 @@ add_default_init_function(_Env, Funs) -> Funs#{ InitName => #{attrs => [], args => [], return => {tuple, []}, - body => {tuple, []}} }; + body => {tuple, [], []}} }; _ -> Funs end. @@ -1315,7 +1315,7 @@ lifted_fun(FVs, Xs, Body) -> Closure :: fexpr(). make_closure(FVs, Xs, Body) -> Fun = add_lambda_fun(lifted_fun(FVs, Xs, Body)), - Tup = fun([Y]) -> Y; (Ys) -> {tuple, Ys} end, + Tup = fun([Y]) -> Y; (Ys) -> {tuple, [], Ys} end, {closure, get_fann(Body), Fun, Tup([{var, [], Y} || Y <- FVs])}. -spec lambda_lift_expr(state_layout(), fexpr()) -> Closure when @@ -1353,7 +1353,7 @@ lambda_lift_expr(Layout, Expr) -> {builtin, Ann, B, As} -> {builtin, Ann, B, lambda_lift_exprs(Layout, As)}; {remote, Ann, ArgsT, RetT, Ct, F, As} -> {remote, Ann, ArgsT, RetT, lambda_lift_expr(Layout, Ct), F, lambda_lift_exprs(Layout, As)}; {con, Ann, Ar, C, As} -> {con, Ann, Ar, C, lambda_lift_exprs(Layout, As)}; - {tuple, As} -> {tuple, lambda_lift_exprs(Layout, As)}; + {tuple, Ann, As} -> {tuple, Ann, lambda_lift_exprs(Layout, As)}; {proj, Ann, A, I} -> {proj, Ann, lambda_lift_expr(Layout, A), I}; {set_proj, Ann, A, I, B} -> {set_proj, Ann, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)}; {op, Ann, Op, As} -> {op, Ann, Op, lambda_lift_exprs(Layout, As)}; @@ -1429,8 +1429,8 @@ bind_subexpressions(Expr) -> bottom_up(fun bind_subexpressions/2, Expr). -spec bind_subexpressions(expr_env(), fexpr()) -> fexpr(). -bind_subexpressions(_, {tuple, Es}) -> - ?make_lets(Xs, Es, {tuple, Xs}); +bind_subexpressions(_, {tuple, Ann, Es}) -> + ?make_lets(Xs, Es, {tuple, Ann, Xs}); bind_subexpressions(_, {set_proj, Ann, A, I, B}) -> ?make_lets([X, Y], [A, B], {set_proj, Ann, X, I, Y}); bind_subexpressions(_, E) -> E. @@ -1522,7 +1522,7 @@ simplifier(Expr) -> %% (e₀, .., en).i -> %% let _ = e₀ in .. let x = ei in .. let _ = en in x -simplify(_Env, {proj, FAnn, {tuple, Es}, I}) -> +simplify(_Env, {proj, FAnn, {tuple, _, Es}, I}) -> It = lists:nth(I + 1, Es), X = fresh_name(), Dup = safe_to_duplicate(It), @@ -1565,7 +1565,7 @@ simpl_proj(Env, I, Expr) -> case Expr of false -> false; {var, _, X} -> simpl_proj(Env, I, maps:get(X, Env, false)); - {tuple, Es} -> IfSafe(lists:nth(I + 1, Es)); + {tuple, _, Es} -> IfSafe(lists:nth(I + 1, Es)); {set_proj, _, _, I, Val} -> IfSafe(Val); {set_proj, _, E, _, _} -> simpl_proj(Env, I, E); {proj, _, E, J} -> simpl_proj(Env, I, simpl_proj(Env, J, E)); @@ -1623,7 +1623,7 @@ simpl_case(Env, E, [{'case', Pat, Body} | Alts]) -> end. -spec match_pat(fsplit_pat(), fexpr()) -> false | [{var_name(), fexpr()}]. -match_pat({tuple, Xs}, {tuple, Es}) -> lists:zip(Xs, Es); +match_pat({tuple, _, Xs}, {tuple, _, Es}) -> lists:zip(Xs, Es); match_pat({con, _, _, C, Xs}, {con, _, _, C, Es}) -> lists:zip(Xs, Es); match_pat(L, {lit, _, L}) -> []; match_pat(nil, nil) -> []; @@ -1642,16 +1642,16 @@ constructor_form(Env, Expr) -> end; {set_proj, _, E, I, V} -> case constructor_form(Env, E) of - {tuple, Es} -> {tuple, setnth(I + 1, V, Es)}; - _ -> false + {tuple, Ann, Es} -> {tuple, Ann, setnth(I + 1, V, Es)}; + _ -> false end; {proj, _, E, I} -> case constructor_form(Env, E) of - {tuple, Es} -> constructor_form(Env, lists:nth(I + 1, Es)); - _ -> false + {tuple, _, Es} -> constructor_form(Env, lists:nth(I + 1, Es)); + _ -> false end; {con, _, _, _, _} -> Expr; - {tuple, _} -> Expr; + {tuple, _, _} -> Expr; {lit, _, _} -> Expr; nil -> Expr; {op, _, '::', _} -> Expr; @@ -1675,18 +1675,18 @@ drop_unused_lets(_, Expr) -> Expr. %% -- Static analysis -------------------------------------------------------- -spec safe_to_duplicate(fexpr()) -> boolean(). -safe_to_duplicate({lit, _, _}) -> true; -safe_to_duplicate({var, _, _}) -> true; -safe_to_duplicate(nil) -> true; -safe_to_duplicate({tuple, []}) -> true; -safe_to_duplicate(_) -> false. +safe_to_duplicate({lit, _, _}) -> true; +safe_to_duplicate({var, _, _}) -> true; +safe_to_duplicate(nil) -> true; +safe_to_duplicate({tuple, _, []}) -> true; +safe_to_duplicate(_) -> false. -spec read_only(fexpr() | fsplit() | fcase() | [fexpr()] | [fcase()]) -> boolean(). read_only({lit, _, _}) -> true; read_only({var, _, _}) -> true; read_only(nil) -> true; read_only({con, _, _, _, Es}) -> read_only(Es); -read_only({tuple, Es}) -> read_only(Es); +read_only({tuple, _, Es}) -> read_only(Es); read_only({proj, _, E, _}) -> read_only(E); read_only({set_proj, _, A, _, B}) -> read_only([A, B]); read_only({op, _, _, Es}) -> read_only(Es); @@ -1910,7 +1910,7 @@ pat_vars({int, _}) -> []; pat_vars({string, _}) -> []; pat_vars(nil) -> []; pat_vars({'::', P, Q}) -> pat_vars(P) ++ pat_vars(Q); -pat_vars({tuple, Ps}) -> pat_vars(Ps); +pat_vars({tuple, _, Ps}) -> pat_vars(Ps); pat_vars({con, _, _, _, Ps}) -> pat_vars(Ps); pat_vars({assign, X, P}) -> pat_vars(X) ++ pat_vars(P); pat_vars(Ps) when is_list(Ps) -> [X || P <- Ps, X <- pat_vars(P)]. @@ -1922,7 +1922,7 @@ fsplit_pat_vars({int, _}) -> []; fsplit_pat_vars({string, _}) -> []; fsplit_pat_vars(nil) -> []; fsplit_pat_vars({'::', P, Q}) -> [P, Q]; -fsplit_pat_vars({tuple, Ps}) -> Ps; +fsplit_pat_vars({tuple, _, Ps}) -> Ps; fsplit_pat_vars({con, _, _, _, Ps}) -> Ps. -spec free_vars(fexpr() | [fexpr()]) -> [var_name()]. @@ -1940,8 +1940,8 @@ free_vars(Expr) -> {builtin, _, _, As} -> free_vars(As); {builtin_u, _, _, _} -> []; {builtin_u, _, _, _, _} -> []; %% Typereps are always literals - {con, _, _, _, As} -> free_vars(As); - {tuple, As} -> free_vars(As); + {con, _, _, _, As} -> free_vars(As); + {tuple, _, As} -> free_vars(As); {proj, _, A, _} -> free_vars(A); {set_proj, _, A, _, B} -> free_vars([A, B]); {op, _, _, As} -> free_vars(As); @@ -1972,8 +1972,8 @@ used_defs(Expr) -> {builtin, _, _, As} -> used_defs(As); {builtin_u, _, _, _} -> []; {builtin_u, _, _, _, _} -> []; - {con, _, _, _, As} -> used_defs(As); - {tuple, As} -> used_defs(As); + {con, _, _, _, As} -> used_defs(As); + {tuple, _, As} -> used_defs(As); {proj, _, A, _} -> used_defs(A); {set_proj, _, A, _, B} -> used_defs([A, B]); {op, _, _, As} -> used_defs(As); @@ -2008,7 +2008,7 @@ bottom_up(F, Env, Expr) -> {remote, Ann, ArgsT, RetT, Ct, Fun, Es} -> {remote, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun, [bottom_up(F, Env, E) || E <- Es]}; {remote_u, Ann, ArgsT, RetT, Ct, Fun} -> {remote_u, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun}; {con, Ann, Ar, I, Es} -> {con, Ann, Ar, I, [bottom_up(F, Env, E) || E <- Es]}; - {tuple, Es} -> {tuple, [bottom_up(F, Env, E) || E <- Es]}; + {tuple, Ann, Es} -> {tuple, Ann, [bottom_up(F, Env, E) || E <- Es]}; {proj, Ann, E, I} -> {proj, Ann, bottom_up(F, Env, E), I}; {set_proj, Ann, R, I, E} -> {set_proj, Ann, bottom_up(F, Env, R), I, bottom_up(F, Env, E)}; {op, Ann, Op, Es} -> {op, Ann, Op, [bottom_up(F, Env, E) || E <- Es]}; @@ -2068,7 +2068,7 @@ rename(Ren, Expr) -> {remote, Ann, ArgsT, RetT, Ct, F, Es} -> {remote, Ann, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; {remote_u, Ann, ArgsT, RetT, Ct, F} -> {remote_u, Ann, ArgsT, RetT, rename(Ren, Ct), F}; {con, Ann, Ar, I, Es} -> {con, Ann, Ar, I, [rename(Ren, E) || E <- Es]}; - {tuple, Es} -> {tuple, [rename(Ren, E) || E <- Es]}; + {tuple, Ann, Es} -> {tuple, Ann, [rename(Ren, E) || E <- Es]}; {proj, Ann, E, I} -> {proj, Ann, rename(Ren, E), I}; {set_proj, Ann, R, I, E} -> {set_proj, Ann, rename(Ren, R), I, rename(Ren, E)}; {op, Ann, Op, Es} -> {op, Ann, Op, [rename(Ren, E) || E <- Es]}; @@ -2127,9 +2127,9 @@ rename_fpat(Ren, {var, Ann, X}) -> rename_fpat(Ren, {con, Ann, Ar, C, Ps}) -> {Ps1, Ren1} = rename_fpats(Ren, Ps), {{con, Ann, Ar, C, Ps1}, Ren1}; -rename_fpat(Ren, {tuple, Ps}) -> +rename_fpat(Ren, {tuple, Ann, Ps}) -> {Ps1, Ren1} = rename_fpats(Ren, Ps), - {{tuple, Ps1}, Ren1}. + {{tuple, Ann, Ps1}, Ren1}. -spec rename_spat(rename(), fsplit_pat()) -> {fsplit_pat(), rename()}. rename_spat(Ren, P = {bool, _}) -> {P, Ren}; @@ -2146,9 +2146,9 @@ rename_spat(Ren, {var, Ann, X}) -> rename_spat(Ren, {con, Ann, Ar, C, Xs}) -> {Zs, Ren1} = rename_bindings(Ren, Xs), {{con, Ann, Ar, C, Zs}, Ren1}; -rename_spat(Ren, {tuple, Xs}) -> +rename_spat(Ren, {tuple, Ann, Xs}) -> {Zs, Ren1} = rename_bindings(Ren, Xs), - {{tuple, Zs}, Ren1}; + {{tuple, Ann, Zs}, Ren1}; rename_spat(Ren, {assign, X, P}) -> {X1, Ren1} = rename_binding(Ren, X), {P1, Ren2} = rename_binding(Ren1, P), @@ -2304,18 +2304,18 @@ pp_fexpr({con, _, _, I, []}) -> pp_beside(pp_text("C"), pp_int(I)); pp_fexpr({con, Ann, _, I, Es}) -> pp_beside(pp_fexpr({con, Ann, [], I, []}), - pp_fexpr({tuple, Es})); -pp_fexpr({tuple, Es}) -> + pp_fexpr({tuple, Ann, Es})); +pp_fexpr({tuple, _, Es}) -> pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_fexpr(E) || E <- Es]))); pp_fexpr({proj, _, E, I}) -> pp_beside([pp_fexpr(E), pp_text("."), pp_int(I)]); -pp_fexpr({lam, _, Xs, A}) -> - pp_par([pp_fexpr({tuple, [{var, [], X} || X <- Xs]}), pp_text("=>"), +pp_fexpr({lam, Ann, Xs, A}) -> + pp_par([pp_fexpr({tuple, Ann, [{var, Ann, X} || X <- Xs]}), pp_text("=>"), prettypr:nest(2, pp_fexpr(A))]); pp_fexpr({closure, _, Fun, ClEnv}) -> FVs = case ClEnv of - {tuple, Xs} -> Xs; - {var, _, _} -> [ClEnv] + {tuple, _, Xs} -> Xs; + {var, _, _} -> [ClEnv] end, pp_call(pp_text("__CLOSURE__"), [{def, Fun} | FVs]); pp_fexpr({set_proj, _, E, I, A}) -> @@ -2330,8 +2330,8 @@ pp_fexpr({op, _, Op, [A] = Args}) -> false -> pp_call(pp_text(Op), Args); true -> pp_parens(pp_par([pp_text(Op), pp_fexpr(A)])) end; -pp_fexpr({op, _, Op, As}) -> - pp_beside(pp_text(Op), pp_fexpr({tuple, As})); +pp_fexpr({op, Ann, Op, As}) -> + pp_beside(pp_text(Op), pp_fexpr({tuple, Ann, As})); pp_fexpr({'let', _, _, _, _} = Expr) -> Lets = fun Lets({'let', _, Y, C, D}) -> {Ls, E} = Lets(D), @@ -2346,8 +2346,8 @@ pp_fexpr({'let', _, _, _, _} = Expr) -> pp_fexpr(Body) ])); pp_fexpr({builtin_u, _, B, N}) -> pp_beside([pp_text(B), pp_text("/"), pp_text(N)]); -pp_fexpr({builtin_u, _, B, N, TypeArgs}) -> - pp_beside([pp_text(B), pp_text("@"), pp_fexpr({tuple, TypeArgs}), pp_text("/"), pp_text(N)]); +pp_fexpr({builtin_u, Ann, B, N, TypeArgs}) -> + pp_beside([pp_text(B), pp_text("@"), pp_fexpr({tuple, Ann, TypeArgs}), pp_text("/"), pp_text(N)]); pp_fexpr({builtin, _, B, As}) -> pp_call(pp_text(B), As); pp_fexpr({remote_u, _, ArgsT, RetT, Ct, Fun}) -> @@ -2366,7 +2366,7 @@ pp_fexpr({contract_code, Contract}) -> -spec pp_call(prettypr:document(), [fexpr()]) -> prettypr:document(). pp_call(Fun, Args) -> - pp_beside(Fun, pp_fexpr({tuple, Args})). + pp_beside(Fun, pp_fexpr({tuple, [], Args})). -spec pp_call_t(string(), [ftype()]) -> prettypr:document(). pp_call_t(Fun, Args) -> @@ -2406,7 +2406,7 @@ pp_case({'case', Pat, Split}) -> prettypr:nest(2, pp_split(Split))]). -spec pp_pat(fsplit_pat()) -> prettypr:document(). -pp_pat({tuple, Xs}) -> pp_fexpr({tuple, [{var, [], X} || X <- Xs]}); +pp_pat({tuple, Ann, Xs}) -> pp_fexpr({tuple, Ann, [{var, Ann, X} || X <- Xs]}); pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, [], X}, {var, [], Xs}]}); pp_pat({con, Ann, As, I, Xs}) -> pp_fexpr({con, Ann, As, I, [{var, [], X} || X <- Xs]}); pp_pat({var, Ann, X}) -> pp_fexpr({var, Ann, X}); -- 2.30.2 From 835b18649953af21b78a28a39939445a084ad326 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 9 Nov 2022 17:31:30 +0300 Subject: [PATCH 23/92] Add fann() to nil --- src/aeso_ast_to_fcode.erl | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 1277e3d..acb0a8a 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -61,7 +61,7 @@ -type fann() :: [ {line, aeso_syntax:ann_line()} ]. -type fexpr() :: {lit, fann(), flit()} - | nil + | {nil, fann()} | {var, fann(), var_name()} | {def, fann(), fun_name(), [fexpr()]} | {remote, fann(), [ftype()], ftype(), fexpr(), fun_name(), [fexpr()]} @@ -95,7 +95,7 @@ | {bool, false | true} | {int, integer()} | {string, binary()} - | nil + | {nil, fann()} | {'::', var_name(), var_name()} | {con, fann(), arities(), tag(), [var_name()]} | {tuple, fann(), [var_name()]} @@ -667,14 +667,14 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) -> %% Lists expr_to_fcode(Env, _Type, {list, _, Es}) -> lists:foldr(fun(E, L) -> {op, to_fann(aeso_syntax:get_ann(E)), '::', [expr_to_fcode(Env, E), L]} end, - nil, Es); + {nil, []}, Es); expr_to_fcode(Env, _Type, {app, _, {'..', _}, [A, B]}) -> {def_u, Ann, FromTo, _} = resolve_fun(Env, ["ListInternal", "from_to"]), {def, Ann, FromTo, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]}; expr_to_fcode(Env, _Type, {list_comp, As, Yield, []}) -> - {op, to_fann(As), '::', [expr_to_fcode(Env, Yield), nil]}; + {op, to_fann(As), '::', [expr_to_fcode(Env, Yield), {nil, []}]}; expr_to_fcode(Env, _Type, {list_comp, As, Yield, [{comprehension_bind, Pat = {typed, _, _, PatType}, BindExpr}|Rest]}) -> Arg = fresh_name(), Env1 = bind_var(Env, Arg), @@ -686,7 +686,7 @@ expr_to_fcode(Env, _Type, {list_comp, As, Yield, [{comprehension_bind, Pat = {ty expr_to_fcode(Env, Type, {list_comp, As, Yield, [{comprehension_if, _, Cond}|Rest]}) -> make_if(expr_to_fcode(Env, Cond), expr_to_fcode(Env, Type, {list_comp, As, Yield, Rest}), - nil + {nil, []} ); expr_to_fcode(Env, Type, {list_comp, As, Yield, [LV = {letval, _, _, _}|Rest]}) -> expr_to_fcode(Env, Type, {block, As, [LV, {list_comp, As, Yield, Rest}]}); @@ -865,7 +865,7 @@ alts_to_fcode(Env, Type, X, Alts, Switch) -> | {bool, false | true} | {int, integer()} | {string, binary()} - | nil + | {nil, fann()} | {'::', fpat(), fpat()} | {tuple, fann(), [fpat()]} | {con, fann(), arities(), tag(), [fpat()]} @@ -950,7 +950,7 @@ merge_alt(I, X, {P, A}, [{Q, As} | Rest]) -> ({bool, B}, {bool, B}) -> match; ({int, N}, {int, N}) -> match; ({string, S}, {string, S}) -> match; - (nil, nil) -> match; + ({nil, []}, {nil, []}) -> match; ({'::', _, _}, {'::', _, _}) -> match; ({con, _, _, C, _}, {con, _, _, C, _}) -> match; ({con, _, _, _, _}, {con, _, _, _, _}) -> mismatch; @@ -978,7 +978,7 @@ expand(I, X, P, Q, Case = {'case', Ps, E}) -> ({bool, _}) -> bool; ({int, _}) -> int; ({string, _}) -> string; - (nil) -> list; + ({nil, _}) -> list; ({'::', _, _}) -> list; ({con, _, As, _, _}) -> {variant, As} end, @@ -988,7 +988,7 @@ expand(I, X, P, Q, Case = {'case', Ps, E}) -> bool -> {[MkCase({bool, B}, 0) || B <- [false, true]], []}; int -> {[MkCase(Q, 0)], [{P, Case}]}; string -> {[MkCase(Q, 0)], [{P, Case}]}; - list -> {[MkCase(nil, 0), MkCase({'::', fresh_name(), fresh_name()}, 2)], []}; + list -> {[MkCase({nil, []}, 0), MkCase({'::', fresh_name(), fresh_name()}, 2)], []}; {variant, As} -> {[MkCase({con, [], As, C - 1, [fresh_name() || _ <- lists:seq(1, Ar)]}, Ar) || {C, Ar} <- indexed(As)], []} end. @@ -1004,7 +1004,7 @@ split_pat(P = {var, FAnn, _}) -> {{var, FAnn, fresh_name()}, [P]}; split_pat({bool, B}) -> {{bool, B}, []}; split_pat({int, N}) -> {{int, N}, []}; split_pat({string, N}) -> {{string, N}, []}; -split_pat(nil) -> {nil, []}; +split_pat({nil, FAnn}) -> {{nil, FAnn}, []}; split_pat({'::', P, Q}) -> {{'::', fresh_name(), fresh_name()}, [P, Q]}; split_pat({con, FAnn, As, I, Pats}) -> Xs = [fresh_name() || _ <- Pats], @@ -1019,7 +1019,7 @@ split_pat({tuple, FAnn, Pats}) -> split_vars({bool, _}, boolean) -> []; split_vars({int, _}, integer) -> []; split_vars({string, _}, string) -> []; -split_vars(nil, {list, _}) -> []; +split_vars({nil, _}, {list, _}) -> []; split_vars({'::', X, Xs}, {list, T}) -> [{X, T}, {Xs, {list, T}}]; split_vars({assign, X, P}, T) -> [{X, T}, {P, T}]; split_vars({con, _, _, I, Xs}, {variant, Cons}) -> @@ -1065,7 +1065,7 @@ pat_to_fcode(_Env, _Type, {string, _, N}) -> {string, N}; pat_to_fcode(Env, _Type, {list, _, Ps}) -> lists:foldr(fun(P, Qs) -> {'::', pat_to_fcode(Env, P), Qs} - end, nil, Ps); + end, {nil, []}, Ps); pat_to_fcode(Env, _Type, {app, _, {'::', _}, [P, Q]}) -> {'::', pat_to_fcode(Env, P), pat_to_fcode(Env, Q)}; pat_to_fcode(Env, {record_t, Fields}, {record, _, FieldPats}) -> @@ -1346,7 +1346,7 @@ lambda_lift_expr(Layout, {remote_u, Ann, ArgsT, RetT, Ct, F}) -> lambda_lift_expr(Layout, Expr) -> case Expr of {lit, _, _} -> Expr; - nil -> Expr; + {nil, _} -> Expr; {var, _, _} -> Expr; {closure, _, _, _} -> Expr; {def, Ann, D, As} -> {def, Ann, D, lambda_lift_exprs(Layout, As)}; @@ -1626,7 +1626,7 @@ simpl_case(Env, E, [{'case', Pat, Body} | Alts]) -> match_pat({tuple, _, Xs}, {tuple, _, Es}) -> lists:zip(Xs, Es); match_pat({con, _, _, C, Xs}, {con, _, _, C, Es}) -> lists:zip(Xs, Es); match_pat(L, {lit, _, L}) -> []; -match_pat(nil, nil) -> []; +match_pat({nil, _}, {nil, _}) -> []; match_pat({'::', X, Y}, {op, _, '::', [A, B]}) -> [{X, A}, {Y, B}]; match_pat({var, _, X}, E) -> [{X, E}]; match_pat({assign, X, P}, E) -> [{X, E}, {P, E}]; @@ -1653,7 +1653,7 @@ constructor_form(Env, Expr) -> {con, _, _, _, _} -> Expr; {tuple, _, _} -> Expr; {lit, _, _} -> Expr; - nil -> Expr; + {nil, _} -> Expr; {op, _, '::', _} -> Expr; _ -> false end. @@ -1677,14 +1677,14 @@ drop_unused_lets(_, Expr) -> Expr. -spec safe_to_duplicate(fexpr()) -> boolean(). safe_to_duplicate({lit, _, _}) -> true; safe_to_duplicate({var, _, _}) -> true; -safe_to_duplicate(nil) -> true; +safe_to_duplicate({nil, _}) -> true; safe_to_duplicate({tuple, _, []}) -> true; safe_to_duplicate(_) -> false. -spec read_only(fexpr() | fsplit() | fcase() | [fexpr()] | [fcase()]) -> boolean(). read_only({lit, _, _}) -> true; read_only({var, _, _}) -> true; -read_only(nil) -> true; +read_only({nil, _}) -> true; read_only({con, _, _, _, Es}) -> read_only(Es); read_only({tuple, _, Es}) -> read_only(Es); read_only({proj, _, E, _}) -> read_only(E); @@ -1908,7 +1908,7 @@ pat_vars({var, _, X}) -> [X || X /= "_"]; pat_vars({bool, _}) -> []; pat_vars({int, _}) -> []; pat_vars({string, _}) -> []; -pat_vars(nil) -> []; +pat_vars({nil, _}) -> []; pat_vars({'::', P, Q}) -> pat_vars(P) ++ pat_vars(Q); pat_vars({tuple, _, Ps}) -> pat_vars(Ps); pat_vars({con, _, _, _, Ps}) -> pat_vars(Ps); @@ -1920,7 +1920,7 @@ fsplit_pat_vars({var, _, X}) -> [X || X /= "_"]; fsplit_pat_vars({bool, _}) -> []; fsplit_pat_vars({int, _}) -> []; fsplit_pat_vars({string, _}) -> []; -fsplit_pat_vars(nil) -> []; +fsplit_pat_vars({nil, _}) -> []; fsplit_pat_vars({'::', P, Q}) -> [P, Q]; fsplit_pat_vars({tuple, _, Ps}) -> Ps; fsplit_pat_vars({con, _, _, _, Ps}) -> Ps. @@ -1932,7 +1932,7 @@ free_vars(Expr) -> case Expr of {var, _, X} -> [X]; {lit, _, _} -> []; - nil -> []; + {nil, _} -> []; {def, _, _, As} -> free_vars(As); {def_u, _, _, _} -> []; {remote, _, _, _, Ct, _, As} -> free_vars([Ct | As]); @@ -1964,7 +1964,7 @@ used_defs(Expr) -> case Expr of {var, _, _} -> []; {lit, _, _} -> []; - nil -> []; + {nil, _} -> []; {def, _, F, As} -> lists:umerge([F], used_defs(As)); {def_u, _, F, _} -> [F]; {remote, _, _, _, Ct, _, As} -> used_defs([Ct | As]); @@ -1998,7 +1998,7 @@ bottom_up(F, Expr) -> bottom_up(F, #{}, Expr). bottom_up(F, Env, Expr) -> F(Env, case Expr of {lit, _, _} -> Expr; - nil -> Expr; + {nil, _} -> Expr; {var, _, _} -> Expr; {def, Ann, D, Es} -> {def, Ann, D, [bottom_up(F, Env, E) || E <- Es]}; {def_u, _, _, _} -> Expr; @@ -2058,7 +2058,7 @@ get_named_arg({named_arg_t, _, {id, _, Name}, _, Default}, Args) -> rename(Ren, Expr) -> case Expr of {lit, _, _} -> Expr; - nil -> nil; + {nil, Ann} -> {nil, Ann}; {var, Ann, X} -> {var, Ann, rename_var(Ren, X)}; {def, Ann, D, Es} -> {def, Ann, D, [rename(Ren, E) || E <- Es]}; {def_u, _, _, _} -> Expr; @@ -2116,7 +2116,7 @@ rename_fpats(Ren, [P | Ps]) -> rename_fpat(Ren, P = {bool, _}) -> {P, Ren}; rename_fpat(Ren, P = {int, _}) -> {P, Ren}; rename_fpat(Ren, P = {string, _}) -> {P, Ren}; -rename_fpat(Ren, P = nil) -> {P, Ren}; +rename_fpat(Ren, P = {nil, _}) -> {P, Ren}; rename_fpat(Ren, {'::', P, Q}) -> {P1, Ren1} = rename_fpat(Ren, P), {Q1, Ren2} = rename_fpat(Ren1, Q), @@ -2135,7 +2135,7 @@ rename_fpat(Ren, {tuple, Ann, Ps}) -> rename_spat(Ren, P = {bool, _}) -> {P, Ren}; rename_spat(Ren, P = {int, _}) -> {P, Ren}; rename_spat(Ren, P = {string, _}) -> {P, Ren}; -rename_spat(Ren, P = nil) -> {P, Ren}; +rename_spat(Ren, P = {nil, _}) -> {P, Ren}; rename_spat(Ren, {'::', X, Y}) -> {X1, Ren1} = rename_binding(Ren, X), {Y1, Ren2} = rename_binding(Ren1, Y), @@ -2292,7 +2292,7 @@ pp_fexpr({lit, _, {typerep, T}}) -> pp_ftype(T); pp_fexpr({lit, _, {Tag, Lit}}) -> aeso_pretty:expr({Tag, [], Lit}); -pp_fexpr(nil) -> +pp_fexpr({nil, _}) -> pp_text("[]"); pp_fexpr({var, _, X}) -> pp_text(X); pp_fexpr({def, Fun}) -> pp_fun_name(Fun); -- 2.30.2 From 116fefc244def171cb63a6a3e4dc4cf33c279fbf Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Mon, 14 Nov 2022 19:41:20 +0300 Subject: [PATCH 24/92] Fix missing fann() in tuple fexpr() --- src/aeso_ast_to_fcode.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index acb0a8a..93b434d 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -1166,13 +1166,13 @@ set_state({tuple, Ls}, Val) -> ?make_let(X, Val, lists:foldr(fun({I, L}, Code) -> {'let', [], "_", set_state(L, {proj, get_fann(Val), X, I - 1}), Code} - end, {tuple, []}, indexed(Ls))). + end, {tuple, [], []}, indexed(Ls))). -spec get_state(state_layout()) -> fexpr(). get_state({reg, R}) -> {get_state, [], R}; get_state({tuple, Ls}) -> - {tuple, [get_state(L) || L <- Ls]}. + {tuple, [], [get_state(L) || L <- Ls]}. -spec builtin_to_fcode(state_layout(), BuiltinFun, [fexpr()]) -> fexpr() when BuiltinFun :: atom(). %% No need to mention all of them -- 2.30.2 From f0d6031fd5704979e4a3d18a43dfd853539e6118 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 15 Nov 2022 09:53:42 +0300 Subject: [PATCH 25/92] Add dbgloc instruction to fate --- src/aeso_fcode_to_fate.erl | 147 ++++++++++++++++++++----------------- 1 file changed, 80 insertions(+), 67 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index ebc4ebf..2fcd40d 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -268,44 +268,44 @@ lit_to_fate(Env, L) -> term_to_fate(E) -> term_to_fate(#env{}, #{}, E). term_to_fate(GlobEnv, E) -> term_to_fate(GlobEnv, #{}, E). -term_to_fate(GlobEnv, _Env, {lit, L}) -> +term_to_fate(GlobEnv, _Env, {lit, _, L}) -> lit_to_fate(GlobEnv, L); %% negative literals are parsed as 0 - N -term_to_fate(_GlobEnv, _Env, {op, '-', [{lit, {int, 0}}, {lit, {int, N}}]}) -> +term_to_fate(_GlobEnv, _Env, {op, _, '-', [{lit, _, {int, 0}}, {lit, _, {int, N}}]}) -> aeb_fate_data:make_integer(-N); -term_to_fate(_GlobEnv, _Env, nil) -> +term_to_fate(_GlobEnv, _Env, {nil, _}) -> aeb_fate_data:make_list([]); -term_to_fate(GlobEnv, Env, {op, '::', [Hd, Tl]}) -> +term_to_fate(GlobEnv, Env, {op, _, '::', [Hd, Tl]}) -> %% The Tl will translate into a list, because FATE lists are just lists [term_to_fate(GlobEnv, Env, Hd) | term_to_fate(GlobEnv, Env, Tl)]; -term_to_fate(GlobEnv, Env, {tuple, As}) -> +term_to_fate(GlobEnv, Env, {tuple, _, As}) -> aeb_fate_data:make_tuple(list_to_tuple([ term_to_fate(GlobEnv, Env, A) || A<-As])); -term_to_fate(GlobEnv, Env, {con, Ar, I, As}) -> +term_to_fate(GlobEnv, Env, {con, _, Ar, I, As}) -> FateAs = [ term_to_fate(GlobEnv, Env, A) || A <- As ], aeb_fate_data:make_variant(Ar, I, list_to_tuple(FateAs)); -term_to_fate(_GlobEnv, _Env, {builtin, bits_all, []}) -> +term_to_fate(_GlobEnv, _Env, {builtin, _, bits_all, []}) -> aeb_fate_data:make_bits(-1); -term_to_fate(_GlobEnv, _Env, {builtin, bits_none, []}) -> +term_to_fate(_GlobEnv, _Env, {builtin, _, bits_none, []}) -> aeb_fate_data:make_bits(0); -term_to_fate(GlobEnv, _Env, {op, bits_set, [B, I]}) -> +term_to_fate(GlobEnv, _Env, {op, _, bits_set, [B, I]}) -> {bits, N} = term_to_fate(GlobEnv, B), J = term_to_fate(GlobEnv, I), {bits, N bor (1 bsl J)}; -term_to_fate(GlobEnv, _Env, {op, bits_clear, [B, I]}) -> +term_to_fate(GlobEnv, _Env, {op, _, bits_clear, [B, I]}) -> {bits, N} = term_to_fate(GlobEnv, B), J = term_to_fate(GlobEnv, I), {bits, N band bnot (1 bsl J)}; -term_to_fate(GlobEnv, Env, {'let', X, E, Body}) -> +term_to_fate(GlobEnv, Env, {'let', _, X, E, Body}) -> Env1 = Env#{ X => term_to_fate(GlobEnv, Env, E) }, term_to_fate(GlobEnv, Env1, Body); -term_to_fate(_GlobEnv, Env, {var, X}) -> +term_to_fate(_GlobEnv, Env, {var, _, X}) -> case maps:get(X, Env, undefined) of undefined -> throw(not_a_fate_value); V -> V end; -term_to_fate(_GlobEnv, _Env, {builtin, map_empty, []}) -> +term_to_fate(_GlobEnv, _Env, {builtin, _, map_empty, []}) -> aeb_fate_data:make_map(#{}); -term_to_fate(GlobEnv, Env, {op, map_set, [M, K, V]}) -> +term_to_fate(GlobEnv, Env, {op, _, map_set, [M, K, V]}) -> Map = term_to_fate(GlobEnv, Env, M), Map#{term_to_fate(GlobEnv, Env, K) => term_to_fate(GlobEnv, Env, V)}; term_to_fate(_GlobEnv, _Env, _) -> @@ -318,47 +318,52 @@ to_scode(Env, T) -> to_scode1(Env, T) end. -to_scode1(Env, {lit, L}) -> - [push(?i(lit_to_fate(Env, L)))]; +to_scode1(Env, {lit, Ann, L}) -> + [ dbgloc(Env, Ann), push(?i(lit_to_fate(Env, L))) ]; -to_scode1(_Env, nil) -> - [aeb_fate_ops:nil(?a)]; +to_scode1(Env, {nil, Ann}) -> + [ dbgloc(Env, Ann), aeb_fate_ops:nil(?a) ]; -to_scode1(Env, {var, X}) -> - [push(lookup_var(Env, X))]; +to_scode1(Env, {var, Ann, X}) -> + [ dbgloc(Env, Ann), push(lookup_var(Env, X)) ]; -to_scode1(Env, {con, Ar, I, As}) -> +to_scode1(Env, {con, Ann, Ar, I, As}) -> N = length(As), - [[to_scode(notail(Env), A) || A <- As], - aeb_fate_ops:variant(?a, ?i(Ar), ?i(I), ?i(N))]; + [ dbgloc(Env, Ann), + [to_scode(notail(Env), A) || A <- As], + aeb_fate_ops:variant(?a, ?i(Ar), ?i(I), ?i(N)) ]; -to_scode1(Env, {tuple, As}) -> +to_scode1(Env, {tuple, Ann, As}) -> N = length(As), - [[ to_scode(notail(Env), A) || A <- As ], - tuple(N)]; + [ dbgloc(Env, Ann), + [ to_scode(notail(Env), A) || A <- As ], + tuple(N) ]; -to_scode1(Env, {proj, E, I}) -> - [to_scode(notail(Env), E), - aeb_fate_ops:element_op(?a, ?i(I), ?a)]; +to_scode1(Env, {proj, Ann, E, I}) -> + [ dbgloc(Env, Ann), + to_scode(notail(Env), E), + aeb_fate_ops:element_op(?a, ?i(I), ?a) ]; -to_scode1(Env, {set_proj, R, I, E}) -> - [to_scode(notail(Env), E), - to_scode(notail(Env), R), - aeb_fate_ops:setelement(?a, ?i(I), ?a, ?a)]; +to_scode1(Env, {set_proj, Ann, R, I, E}) -> + [ dbgloc(Env, Ann), + to_scode(notail(Env), E), + to_scode(notail(Env), R), + aeb_fate_ops:setelement(?a, ?i(I), ?a, ?a) ]; -to_scode1(Env, {op, Op, Args}) -> - call_to_scode(Env, op_to_scode(Op), Args); +to_scode1(Env, {op, Ann, Op, Args}) -> + [ dbgloc(Env, Ann) | call_to_scode(Env, op_to_scode(Op), Args) ]; -to_scode1(Env, {'let', X, {var, Y}, Body}) -> +to_scode1(Env, {'let', Ann, X, {var, _, Y}, Body}) -> Env1 = bind_var(X, lookup_var(Env, Y), Env), - to_scode(Env1, Body); -to_scode1(Env, {'let', X, Expr, Body}) -> + [ dbgloc(Env, Ann) | to_scode(Env1, Body) ]; +to_scode1(Env, {'let', Ann, X, Expr, Body}) -> {I, Env1} = bind_local(X, Env), - [ to_scode(notail(Env), Expr), + [ dbgloc(Env, Ann), + to_scode(notail(Env), Expr), aeb_fate_ops:store({var, I}, {stack, 0}), to_scode(Env1, Body) ]; -to_scode1(Env = #env{ current_function = Fun, tailpos = true }, {def, Fun, Args}) -> +to_scode1(Env = #env{ current_function = Fun, tailpos = true }, {def, Ann, Fun, Args}) -> %% Tail-call to current function, f(e0..en). Compile to %% [ let xi = ei ] %% [ STORE argi xi ] @@ -371,55 +376,56 @@ to_scode1(Env = #env{ current_function = Fun, tailpos = true }, {def, Fun, Args} aeb_fate_ops:store({var, I}, ?a)], {[I | Is], Acc1, Env2} end, {[], [], Env}, Args), - [ Code, + [ dbgloc(Env, Ann), + Code, [ aeb_fate_ops:store({arg, I}, {var, J}) || {I, J} <- lists:zip(lists:seq(0, length(Vars) - 1), lists:reverse(Vars)) ], loop ]; -to_scode1(Env, {def, Fun, Args}) -> +to_scode1(Env, {def, Ann, Fun, Args}) -> FName = make_function_id(Fun), Lbl = aeb_fate_data:make_string(FName), - call_to_scode(Env, local_call(Env, ?i(Lbl)), Args); -to_scode1(Env, {funcall, Fun, Args}) -> - call_to_scode(Env, [to_scode(Env, Fun), local_call(Env, ?a)], Args); + [ dbgloc(Env, Ann) | call_to_scode(Env, local_call(Env, ?i(Lbl)), Args) ]; +to_scode1(Env, {funcall, Ann, Fun, Args}) -> + [ dbgloc(Env, Ann) | call_to_scode(Env, [to_scode(Env, Fun), local_call(Env, ?a)], Args) ]; -to_scode1(Env, {builtin, B, Args}) -> - builtin_to_scode(Env, B, Args); +to_scode1(Env, {builtin, Ann, B, Args}) -> + [ dbgloc(Env, Ann) | builtin_to_scode(Env, B, Args) ]; -to_scode1(Env, {remote, ArgsT, RetT, Ct, Fun, [Gas, Value, Protected | Args]}) -> +to_scode1(Env, {remote, Ann, ArgsT, RetT, Ct, Fun, [Gas, Value, Protected | Args]}) -> Lbl = make_function_id(Fun), {ArgTypes, RetType0} = typesig_to_scode([{"_", T} || T <- ArgsT], RetT), ArgType = ?i(aeb_fate_data:make_typerep({tuple, ArgTypes})), RetType = ?i(aeb_fate_data:make_typerep(RetType0)), - case Protected of - {lit, {bool, false}} -> + SCode = case Protected of + {lit, _, {bool, false}} -> case Gas of - {builtin, call_gas_left, _} -> + {builtin, _, call_gas_left, _} -> Call = aeb_fate_ops:call_r(?a, Lbl, ArgType, RetType, ?a), call_to_scode(Env, Call, [Ct, Value | Args]); _ -> Call = aeb_fate_ops:call_gr(?a, Lbl, ArgType, RetType, ?a, ?a), call_to_scode(Env, Call, [Ct, Value, Gas | Args]) end; - {lit, {bool, true}} -> + {lit, _, {bool, true}} -> Call = aeb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?i(true)), call_to_scode(Env, Call, [Ct, Value, Gas | Args]); _ -> Call = aeb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?a), call_to_scode(Env, Call, [Ct, Value, Gas, Protected | Args]) - end; + end, + [ dbgloc(Env, Ann) | SCode ]; -to_scode1(_Env, {get_state, Reg}) -> - [push(?s(Reg))]; -to_scode1(Env, {set_state, Reg, Val}) -> - call_to_scode(Env, [{'STORE', ?s(Reg), ?a}, - tuple(0)], [Val]); +to_scode1(Env, {get_state, Ann, Reg}) -> + [ dbgloc(Env, Ann), push(?s(Reg)) ]; +to_scode1(Env, {set_state, Ann, Reg, Val}) -> + [ dbgloc(Env, Ann) | call_to_scode(Env, [{'STORE', ?s(Reg), ?a}, tuple(0)], [Val]) ]; -to_scode1(Env, {closure, Fun, FVs}) -> - to_scode(Env, {tuple, [{lit, {string, make_function_id(Fun)}}, FVs]}); +to_scode1(Env, {closure, Ann, Fun, FVs}) -> + to_scode(Env, {tuple, Ann, [{lit, Ann, {string, make_function_id(Fun)}}, FVs]}); -to_scode1(Env, {switch, Case}) -> - split_to_scode(Env, Case). +to_scode1(Env, {switch, Ann, Case}) -> + [ dbgloc(Env, Ann) | split_to_scode(Env, Case) ]. local_call( Env, Fun) when Env#env.tailpos -> aeb_fate_ops:call_t(Fun); local_call(_Env, Fun) -> aeb_fate_ops:call(Fun). @@ -429,7 +435,7 @@ split_to_scode(Env, {nosplit, Expr}) -> split_to_scode(Env, {split, {tuple, _}, X, Alts}) -> {Def, Alts1} = catchall_to_scode(Env, X, Alts), Arg = lookup_var(Env, X), - Alt = case [ {Xs, Split} || {'case', {tuple, Xs}, Split} <- Alts1 ] of + Alt = case [ {Xs, Split} || {'case', {tuple, _, Xs}, Split} <- Alts1 ] of [] -> missing; [{Xs, S} | _] -> {Code, Env1} = match_tuple(Env, Arg, Xs), @@ -456,7 +462,7 @@ split_to_scode(Env, {split, {list, _}, X, Alts}) -> GetAlt = fun(P) -> case [C || C = {'case', Pat, _} <- Alts1, Pat == P orelse is_tuple(Pat) andalso element(1, Pat) == P] of [] -> missing; - [{'case', nil, S} | _] -> split_to_scode(Env, S); + [{'case', {nil, _}, S} | _] -> split_to_scode(Env, S); [{'case', {'::', Y, Z}, S} | _] -> {I, Env1} = bind_local(Y, Env), {J, Env2} = bind_local(Z, Env1), @@ -475,7 +481,7 @@ split_to_scode(Env, {split, {variant, Cons}, X, Alts}) -> {Def, Alts1} = catchall_to_scode(Env, X, Alts), Arg = lookup_var(Env, X), GetAlt = fun(I) -> - case [{Xs, S} || {'case', {con, _, J, Xs}, S} <- Alts1, I == J] of + case [{Xs, S} || {'case', {con, _, _, J, Xs}, S} <- Alts1, I == J] of [] -> missing; [{Xs, S} | _] -> {Code, Env1} = match_variant(Env, Arg, Xs), @@ -507,7 +513,7 @@ literal_split_to_scode(Env, Type, Arg, [{'case', Lit, Body} | Alts], Def) when T catchall_to_scode(Env, X, Alts) -> catchall_to_scode(Env, X, Alts, []). -catchall_to_scode(Env, X, [{'case', {var, Y}, Split} | _], Acc) -> +catchall_to_scode(Env, X, [{'case', {var, _, Y}, Split} | _], Acc) -> Env1 = bind_var(Y, lookup_var(Env, X), Env), {split_to_scode(Env1, Split), lists:reverse(Acc)}; catchall_to_scode(Env, X, [Alt | Alts], Acc) -> @@ -649,7 +655,7 @@ builtin_to_scode(Env, chain_bytecode_hash, [_Addr] = Args) -> builtin_to_scode(Env, chain_clone, [InitArgsT, GasCap, Value, Prot, Contract | InitArgs]) -> case GasCap of - {builtin, call_gas_left, _} -> + {builtin, _, call_gas_left, _} -> call_to_scode(Env, aeb_fate_ops:clone(?a, ?a, ?a, ?a), [Contract, InitArgsT, Value, Prot | InitArgs] ); @@ -751,6 +757,12 @@ push(A) -> {'STORE', ?a, A}. tuple(0) -> push(?i({tuple, {}})); tuple(N) -> aeb_fate_ops:tuple(?a, N). +dbgloc(Env, Ann) -> + case proplists:get_value(debug_info, Env#env.options, false) of + false -> []; + true -> [{'DBGLOC', proplists:get_value(line, Ann, -1)}] + end. + %% -- Phase II --------------------------------------------------------------- %% Optimize @@ -886,6 +898,7 @@ attributes(I) -> loop -> Impure(pc, []); switch_body -> Pure(none, []); 'RETURN' -> Impure(pc, []); + {'DBGLOC', _} -> Impure(pc, []); {'RETURNR', A} -> Impure(pc, A); {'CALL', A} -> Impure(?a, [A]); {'CALL_R', A, _, B, C, D} -> Impure(?a, [A, B, C, D]); -- 2.30.2 From 363a550402ff4493ef3b41434e6413c0c3088a9e Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 17 Nov 2022 15:18:44 +0300 Subject: [PATCH 26/92] Add instructions lines to the debugging result --- src/aeso_compiler.erl | 7 +++-- src/aeso_fcode_to_fate.erl | 61 ++++++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/src/aeso_compiler.erl b/src/aeso_compiler.erl index 7a0d069..41f7de5 100644 --- a/src/aeso_compiler.erl +++ b/src/aeso_compiler.erl @@ -119,7 +119,7 @@ from_string1(ContractString, Options) -> , warnings := Warnings } = string_to_code(ContractString, Options), #{ child_con_env := ChildContracts } = FCodeEnv, SavedFreshNames = maps:get(saved_fresh_names, FCodeEnv, #{}), - {FateCode, VarsRegs} = aeso_fcode_to_fate:compile(ChildContracts, FCode, SavedFreshNames, Options), + {FateCode, VarsRegs, DbglocMap} = aeso_fcode_to_fate:compile(ChildContracts, FCode, SavedFreshNames, Options), pp_assembler(FateCode, Options), ByteCode = aeb_fate_code:serialize(FateCode, []), {ok, Version} = version(), @@ -132,7 +132,8 @@ from_string1(ContractString, Options) -> payable => maps:get(payable, FCode), warnings => Warnings }, - ResDbg = Res#{variables_registers => VarsRegs}, + ResDbg = Res#{ variables_registers => VarsRegs, + instructions_lines => DbglocMap }, FinalRes = case proplists:get_value(debug_info, Options, false) of true -> ResDbg; @@ -204,7 +205,7 @@ add_extra_call(Contract0, Call, Options) -> #{fcode := OrgFcode , fcode_env := #{child_con_env := ChildContracts} , ast := Ast} = string_to_code(Contract0, Options), - {FateCode, _} = aeso_fcode_to_fate:compile(ChildContracts, OrgFcode, #{}, []), + {FateCode, _, _} = aeso_fcode_to_fate:compile(ChildContracts, OrgFcode, #{}, []), %% collect all hashes and compute the first name without hash collision to SymbolHashes = maps:keys(aeb_fate_code:symbols(FateCode)), CallName = first_none_match(?CALL_NAME, SymbolHashes, diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 2fcd40d..0f8a549 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -93,12 +93,57 @@ compile1(ChildContracts, FCode, SavedFreshNames, Options) -> SFuns = functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options), SFuns1 = optimize_scode(SFuns, Options), FateCode = to_basic_blocks(SFuns1), - ?debug(compile, Options, "~s\n", [aeb_fate_asm:pp(FateCode)]), - FateCode1 = case proplists:get_value(include_child_contract_symbols, Options, false) of - false -> FateCode; - true -> add_child_symbols(ChildContracts, FateCode) + {FateCode1, DbglocMap} = + case proplists:get_value(debug_info, Options, false) of + true -> remove_dbgloc(FateCode); + false -> {FateCode, #{}} + end, + ?debug(compile, Options, "~s\n", [aeb_fate_asm:pp(FateCode1)]), + FateCode2 = case proplists:get_value(include_child_contract_symbols, Options, false) of + false -> FateCode1; + true -> add_child_symbols(ChildContracts, FateCode1) end, - {FateCode1, get_variables_registers()}. + {FateCode2, get_variables_registers(), DbglocMap}. + +-spec block_dbgloc_map(bcode()) -> DbglocMap when + DbglocMap :: #{integer() => integer()}. +block_dbgloc_map(BB) -> block_dbgloc_map(BB, 0, maps:new()). + +-spec block_dbgloc_map(bcode(), integer(), DbglocMap) -> DbglocMap when + DbglocMap :: #{integer() => integer()}. +block_dbgloc_map([], _, DbglocMap) -> + DbglocMap; +block_dbgloc_map([{'DBGLOC', Line} | Rest], Index, DbglocMap) -> + block_dbgloc_map(Rest, Index, maps:put(Index, Line, DbglocMap)); +block_dbgloc_map([_ | Rest], Index, DbglocMap) -> + block_dbgloc_map(Rest, Index + 1, DbglocMap). + +-spec remove_dbgloc(aeb_fate_code:fcode()) -> {aeb_fate_code:fcode(), DbglocMap} when + DbglocMap :: #{integer() => integer()}. +remove_dbgloc(FateCode) -> + RemoveDbglocFromBBs = + fun(_, BB) -> + IsDbg = fun({'DBGLOC', _}) -> false; + (_) -> true + end, + lists:filter(IsDbg, BB) + end, + + RemoveDbglocFromFuns = + fun(_, Fun = {_, _, BBs}) -> + NewBBs = maps:map(RemoveDbglocFromBBs, BBs), + setelement(3, Fun, NewBBs) + end, + + DbglocMapFromBBs = + fun(_, {_, _, BBs}) -> + maps:map(fun(_, BB) -> block_dbgloc_map(BB) end, BBs) + end, + + OldFuns = aeb_fate_code:functions(FateCode), + DbglocMap = maps:map(DbglocMapFromBBs, OldFuns), + NewFuns = maps:map(RemoveDbglocFromFuns, OldFuns), + {aeb_fate_code:update_functions(FateCode, NewFuns), DbglocMap}. make_function_id(X) -> aeb_fate_code:symbol_identifier(make_function_name(X)). @@ -760,7 +805,11 @@ tuple(N) -> aeb_fate_ops:tuple(?a, N). dbgloc(Env, Ann) -> case proplists:get_value(debug_info, Env#env.options, false) of false -> []; - true -> [{'DBGLOC', proplists:get_value(line, Ann, -1)}] + true -> + case proplists:get_value(line, Ann) of + undefined -> []; + Line -> [{'DBGLOC', Line}] + end end. %% -- Phase II --------------------------------------------------------------- -- 2.30.2 From 694646fa3dc6b21143ee562771375614aae08034 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 17 Nov 2022 15:29:38 +0300 Subject: [PATCH 27/92] Fix compiler tests --- src/aeso_fcode_to_fate.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 0f8a549..b227ff1 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -279,7 +279,7 @@ serialize_contract_code(Env, C) -> Options = Env#env.options, SavedFreshNames = Env#env.saved_fresh_names, FCode = maps:get(C, Env#env.child_contracts), - {FateCode, _} = compile1(Env#env.child_contracts, FCode, SavedFreshNames, Options), + {FateCode, _, _} = compile1(Env#env.child_contracts, FCode, SavedFreshNames, Options), ByteCode = aeb_fate_code:serialize(FateCode, []), {ok, Version} = aeso_compiler:version(), OriginalSourceCode = proplists:get_value(original_src, Options, ""), -- 2.30.2 From 683747bc386a307c610ae429d57b1b9ba655f255 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 17 Nov 2022 16:41:36 +0300 Subject: [PATCH 28/92] Fix calldata tests --- src/aeso_code_analysis.erl | 214 +++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 src/aeso_code_analysis.erl diff --git a/src/aeso_code_analysis.erl b/src/aeso_code_analysis.erl new file mode 100644 index 0000000..5c78f0f --- /dev/null +++ b/src/aeso_code_analysis.erl @@ -0,0 +1,214 @@ +-module(aeso_code_analysis). + +-export([analyze/1]). + +%-record(env, {vars = [] :: list()}). +% +%-type env() :: #env{}. + +-record(analysis, + { defined_types = sets:new() :: sets:set() + , defined_funs = sets:new() :: sets:set() + , used_types = sets:new() :: sets:set() + , used_funs = sets:new() :: sets:set() + , used_includes = sets:new() :: sets:set() + , unused_stateful = sets:new() :: sets:set() + %, used_vars = [] :: list() + %, defined_vars = [] :: list() + %, used_consts = [] :: list() + %, shadowing_pairs = [] :: list() + %, unused_retval = [] :: list() + }). + +%-type analysis() :: #analysis{}. + +-define(P(X), io:format(??X ++ ":\n~p\n", [X])). + +-record(alg, + { zero :: A + , plus :: fun((A, A) -> A) + , scoped :: fun((A, A) -> A) }). + +work(expr, X = {qid, Ann, Fun}) -> + ?P(X), + ?P(aeso_syntax:get_ann(stateful, Ann, none)), + ?P(""), + #analysis{used_funs = sets:from_list([Fun])}; +work(type, {qid, _, Type}) -> + #analysis{used_types = sets:from_list([Type])}; +work(bind_type, {id, _, Type}) -> + #analysis{defined_types = sets:from_list([Type])}; +work(_, _) -> + #analysis{}. + +-spec analyze(aeso_syntax:ast()) -> ok. +analyze([{Contract, _Ann, {con, _, _ConName}, _Impls, Decls} | Rest]) + when Contract == contract_main; + Contract == contract_child -> + analyze_contract(Decls), + analyze(Rest); +analyze([{namespace, _Ann, {con, _, _NSName}, Decls} | Rest]) -> + analyze_contract(Decls), + analyze(Rest); +analyze([]) -> + error("End of code analysis"). + +analyze_contract(Decls) -> + Funs = [ Fun || Fun = {letfun, _, _, _, _, _} <- Decls], + _Types = [ Def || Def = {type_def, _, _, _, _} <- Decls ], + _Consts = [ Const || Const = {letval, _, _, _} <- Decls ], + + Alg = + #alg{ zero = #analysis{} + , plus = fun merge/2 + , scoped = fun merge/2 }, + Res0 = aeso_syntax_utils:fold( + Alg, + fun work/2, + decl, + Decls), + Res = merge(Res0, #analysis{defined_funs = Funs}), + UsedTypes = sets:to_list(Res#analysis.used_types), + UsedFuns = sets:to_list(Res#analysis.used_funs), + ?P(UsedFuns), + ?P(UsedTypes), + + %Res = [ {Name, analyze_fun(Fun)} || Fun = {letfun, _, {id, _, Name}, _, _, _} <- Funs ], + + ?P(Res). +% +%analyze_fun({letfun, _, _FunId, _Args, _, GuardedBodies}) -> +% lists:foldl(fun merge/2, #analysis{}, [(analyze_expr(#env{}, Body)) || {guarded, _, _, Body} <- GuardedBodies ]). +% +%-spec analyze_expr(env(), aeso_syntax:expr()) -> analysis(). +%analyze_expr(Env, {lam, _, Args, Expr}) -> +% NewVars = [ Id || {arg, _, Id, _} <- Args ], +% Env1 = lists:foldl(fun bind_var/2, Env, NewVars), +% Analysis = analyze_expr(Env1, Expr), +% Analysis#analysis{defined_vars = Analysis#analysis.defined_vars ++ NewVars}; +%%analyze_expr(Env, {'if', ann(), expr(), expr(), expr()}) -> +%% ok; +%%analyze_expr(Env, {switch, ann(), expr(), [alt()]}) -> +%% ok; +%analyze_expr(Env, {app, _, Expr, _Args}) -> +% analyze_expr(Env, Expr); +%%analyze_expr(Env, {proj, ann(), expr(), id()}) -> +%% ok; +%analyze_expr(Env, {tuple, _, Exprs}) -> +% lists:foldl(fun merge/2, #analysis{}, [ analyze_expr(Env, Expr) || Expr <- Exprs ]); +%%analyze_expr(Env, {list, ann(), [expr()]}) -> +%% ok; +%%analyze_expr(Env, {list_comp, ann(), expr(), [comprehension_exp()]}) -> +%% ok; +%analyze_expr(Env, {typed, _, Expr, Type}) -> +% merge(analyze_expr(Env, Expr), analyze_type(Env, Type)); +%%analyze_expr(Env, {record_or_map(), ann(), [field(expr())]}) -> +%% ok; +%%analyze_expr(Env, {record_or_map(), ann(), expr(), [field(expr())]}) -> +%% ok; +%%analyze_expr(Env, {map, ann(), [{expr(), expr()}]}) -> +%% ok; +%%analyze_expr(Env, {map_get, ann(), expr(), expr()}) -> +%% ok; +%%analyze_expr(Env, {map_get, ann(), expr(), expr(), expr()}) -> +%% ok; +%analyze_expr(Env, {block, _, Stmts}) -> +% analyze_block(Env, Stmts); +%%analyze_expr(Env, {op(), ann()}) -> +%% ok; +%analyze_expr(_Env, {int, _, _}) -> +% #analysis{}; +%analyze_expr(Env, Id = {id, _, _}) -> +% #analysis{used_vars = [lookup_var(Id, Env)]}; +%analyze_expr(_Env, {qcon, _, _}) -> +% #analysis{}. +%%analyze_expr(Env, QId = {qid, _, _}) -> +%% #analysis{used_funs = lookup_fun(QId, Env)}. +%%analyze_expr(Env, qid() | con() | qcon()) -> +%% ok; +%%analyze_expr(Env, constant()) -> +%% ok; +%%analyze_expr(Env, letpat()) -> +%% ok. +% +%analyze_block(_Env, []) -> +% #analysis{}; +%analyze_block(Env, [E]) -> +% analyze_expr(Env, E); +%analyze_block(Env, [{letval, _, {typed, _, Id = {id, _, _}, _}, Expr} | Stmts]) -> +% Env1 = bind_var(Id, Env), +% Analysis = analyze_block(Env1, Stmts), +% Analysis2 = merge(Analysis, analyze_expr(Env1, Expr)), +% Analysis2#analysis{defined_vars = Analysis2#analysis.defined_vars ++ [Id]}. +% +%analyze_type(_Env, {id, _, Id}) -> +% #analysis{used_types = [Id]}; +%analyze_type(_Env, {qid, _, QId}) -> +% #analysis{used_types = [QId]}; +%analyze_type(Env, {fun_t, _, _, Types, Type}) -> +% merge(lists:foldl(fun merge/2, #analysis{}, [analyze_type(Env, T) || T <- Types]), analyze_type(Env, Type)); +%analyze_type(_Env, {tuple_t, _, _}) -> +% #analysis{}. +% +%bind_var(VarId, Env = #env{vars = Vars}) -> +% check_shadowing(VarId, Vars), +% Env#env{vars = [VarId | Vars]}. +% +%check_shadowing(Var = {id, _, VarName}, Ids) -> +% Shadowed = +% lists:search(fun({id, _, Name}) when Name == VarName -> true; +% (_) -> false +% end, Ids), +% case Shadowed of +% false -> +% #analysis{}; +% {value, ShadowedVar} -> +% #analysis{shadowing_pairs = [{Var, ShadowedVar}]} +% end. +% +%lookup_var({id, _, VarName}, Env) -> +% {value, Var}= +% lists:search( +% fun({id, _, Name}) when Name == VarName -> true; +% (_) -> false +% end, Env#env.vars), +% Var. + + +merge(A1, A2) -> + #analysis{ used_types = sets:union(A1#analysis.used_types, A2#analysis.used_types) + , used_funs = sets:union(A1#analysis.used_funs, A2#analysis.used_funs) }. + + +%% the set of unused functions is the different between the 2 sets: +%% - In a contract: +%% * all user-defined functions +%% * all function calls +%% - In a namespace: +%% * all user-defined private functions +%% * all function calls +%% Note: this only applies to functions, not entrypoints + +%% Unused variables: +%% ----------------- +%% Scope: function +%% Algo: if a variable is not used in its current scope, then it's reported. +%% Functions that are declared in one scope but not used, and then declared +%% in a different scope and used, should be considered. +%% +%% Unused stateful: +%% ---------------- +%% Scope: function +%% Algo: check all function calls in the function, if none of them requires +%% stateful, then we say that it's unused. +%% +%% Unused constants: +%% ----------------- +%% Scope: contract or namespace +%% Algo: same as variables, but the scope is fixed to the contract or the namespace. +%% +%% Unused typedefs: +%% ---------------- +%% Scope: contract or namespace +%% Algo: check the types of all expressions in the contract or namespace, if the type +%% doesn't show up anywhere, then the typedef is not used. -- 2.30.2 From 5ef52c0dc3ef3ee7aceb3df3605cc411fb65e2b2 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 17 Nov 2022 17:05:33 +0300 Subject: [PATCH 29/92] Rname Ann to FAnn when the type is fann() --- src/aeso_ast_to_fcode.erl | 222 +++++++++++++++++++------------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 93b434d..bb8cb53 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -670,8 +670,8 @@ expr_to_fcode(Env, _Type, {list, _, Es}) -> {nil, []}, Es); expr_to_fcode(Env, _Type, {app, _, {'..', _}, [A, B]}) -> - {def_u, Ann, FromTo, _} = resolve_fun(Env, ["ListInternal", "from_to"]), - {def, Ann, FromTo, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]}; + {def_u, FAnn, FromTo, _} = resolve_fun(Env, ["ListInternal", "from_to"]), + {def, FAnn, FromTo, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]}; expr_to_fcode(Env, _Type, {list_comp, As, Yield, []}) -> {op, to_fann(As), '::', [expr_to_fcode(Env, Yield), {nil, []}]}; @@ -681,8 +681,8 @@ expr_to_fcode(Env, _Type, {list_comp, As, Yield, [{comprehension_bind, Pat = {ty Bind = {lam, to_fann(As), [Arg], expr_to_fcode(Env1, {switch, As, {typed, As, {id, As, Arg}, PatType}, [{'case', As, Pat, [{guarded, As, [], {list_comp, As, Yield, Rest}}]}, {'case', As, {id, As, "_"}, [{guarded, As, [], {list, As, []}}]}]})}, - {def_u, Ann, FlatMap, _} = resolve_fun(Env, ["ListInternal", "flat_map"]), - {def, Ann, FlatMap, [Bind, expr_to_fcode(Env, BindExpr)]}; + {def_u, FAnn, FlatMap, _} = resolve_fun(Env, ["ListInternal", "flat_map"]), + {def, FAnn, FlatMap, [Bind, expr_to_fcode(Env, BindExpr)]}; expr_to_fcode(Env, Type, {list_comp, As, Yield, [{comprehension_if, _, Cond}|Rest]}) -> make_if(expr_to_fcode(Env, Cond), expr_to_fcode(Env, Type, {list_comp, As, Yield, Rest}), @@ -1336,35 +1336,35 @@ lambda_lift_expr(Layout, UExpr) when element(1, UExpr) == def_u; element(1, UExp def_u -> {def, [], F, Args} end, make_closure([], Xs, Body); -lambda_lift_expr(Layout, {remote_u, Ann, ArgsT, RetT, Ct, F}) -> +lambda_lift_expr(Layout, {remote_u, FAnn, ArgsT, RetT, Ct, F}) -> FVs = free_vars(Ct), Ct1 = lambda_lift_expr(Layout, Ct), NamedArgCount = 3, Xs = [ lists:concat(["arg", I]) || I <- lists:seq(1, length(ArgsT) + NamedArgCount) ], Args = [{var, [], X} || X <- Xs], - make_closure(FVs, Xs, {remote, Ann, ArgsT, RetT, Ct1, F, Args}); + make_closure(FVs, Xs, {remote, FAnn, ArgsT, RetT, Ct1, F, Args}); lambda_lift_expr(Layout, Expr) -> case Expr of - {lit, _, _} -> Expr; - {nil, _} -> Expr; - {var, _, _} -> Expr; - {closure, _, _, _} -> Expr; - {def, Ann, D, As} -> {def, Ann, D, lambda_lift_exprs(Layout, As)}; - {builtin, Ann, B, As} -> {builtin, Ann, B, lambda_lift_exprs(Layout, As)}; - {remote, Ann, ArgsT, RetT, Ct, F, As} -> {remote, Ann, ArgsT, RetT, lambda_lift_expr(Layout, Ct), F, lambda_lift_exprs(Layout, As)}; - {con, Ann, Ar, C, As} -> {con, Ann, Ar, C, lambda_lift_exprs(Layout, As)}; - {tuple, Ann, As} -> {tuple, Ann, lambda_lift_exprs(Layout, As)}; - {proj, Ann, A, I} -> {proj, Ann, lambda_lift_expr(Layout, A), I}; - {set_proj, Ann, A, I, B} -> {set_proj, Ann, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)}; - {op, Ann, Op, As} -> {op, Ann, Op, lambda_lift_exprs(Layout, As)}; - {'let', Ann, X, A, B} -> {'let', Ann, X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)}; - {funcall, Ann, A, Bs} -> {funcall, Ann, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)}; - {set_state, Ann, R, A} -> {set_state, Ann, R, lambda_lift_expr(Layout, A)}; - {get_state, _, _} -> Expr; - {switch, Ann, S} -> {switch, Ann, lambda_lift_expr(Layout, S)}; - {split, Type, X, Alts} -> {split, Type, X, lambda_lift_exprs(Layout, Alts)}; - {nosplit, A} -> {nosplit, lambda_lift_expr(Layout, A)}; - {'case', P, S} -> {'case', P, lambda_lift_expr(Layout, S)} + {lit, _, _} -> Expr; + {nil, _} -> Expr; + {var, _, _} -> Expr; + {closure, _, _, _} -> Expr; + {def, FAnn, D, As} -> {def, FAnn, D, lambda_lift_exprs(Layout, As)}; + {builtin, FAnn, B, As} -> {builtin, FAnn, B, lambda_lift_exprs(Layout, As)}; + {remote, FAnn, ArgsT, RetT, Ct, F, As} -> {remote, FAnn, ArgsT, RetT, lambda_lift_expr(Layout, Ct), F, lambda_lift_exprs(Layout, As)}; + {con, FAnn, Ar, C, As} -> {con, FAnn, Ar, C, lambda_lift_exprs(Layout, As)}; + {tuple, FAnn, As} -> {tuple, FAnn, lambda_lift_exprs(Layout, As)}; + {proj, FAnn, A, I} -> {proj, FAnn, lambda_lift_expr(Layout, A), I}; + {set_proj, FAnn, A, I, B} -> {set_proj, FAnn, lambda_lift_expr(Layout, A), I, lambda_lift_expr(Layout, B)}; + {op, FAnn, Op, As} -> {op, FAnn, Op, lambda_lift_exprs(Layout, As)}; + {'let', FAnn, X, A, B} -> {'let', FAnn, X, lambda_lift_expr(Layout, A), lambda_lift_expr(Layout, B)}; + {funcall, FAnn, A, Bs} -> {funcall, FAnn, lambda_lift_expr(Layout, A), lambda_lift_exprs(Layout, Bs)}; + {set_state, FAnn, R, A} -> {set_state, FAnn, R, lambda_lift_expr(Layout, A)}; + {get_state, _, _} -> Expr; + {switch, FAnn, S} -> {switch, FAnn, lambda_lift_expr(Layout, S)}; + {split, Type, X, Alts} -> {split, Type, X, lambda_lift_exprs(Layout, Alts)}; + {nosplit, A} -> {nosplit, lambda_lift_expr(Layout, A)}; + {'case', P, S} -> {'case', P, lambda_lift_expr(Layout, S)} end. -spec lambda_lift_exprs(state_layout(), [fexpr()]) -> [Closure] when @@ -1429,10 +1429,10 @@ bind_subexpressions(Expr) -> bottom_up(fun bind_subexpressions/2, Expr). -spec bind_subexpressions(expr_env(), fexpr()) -> fexpr(). -bind_subexpressions(_, {tuple, Ann, Es}) -> - ?make_lets(Xs, Es, {tuple, Ann, Xs}); -bind_subexpressions(_, {set_proj, Ann, A, I, B}) -> - ?make_lets([X, Y], [A, B], {set_proj, Ann, X, I, Y}); +bind_subexpressions(_, {tuple, FAnn, Es}) -> + ?make_lets(Xs, Es, {tuple, FAnn, Xs}); +bind_subexpressions(_, {set_proj, FAnn, A, I, B}) -> + ?make_lets([X, Y], [A, B], {set_proj, FAnn, X, I, Y}); bind_subexpressions(_, E) -> E. -spec make_lets([fexpr()], fun(([fexpr()]) -> fexpr())) -> fexpr(). @@ -1468,15 +1468,15 @@ inline_local_functions(_, Expr) -> Expr. let_floating(Expr) -> bottom_up(fun let_float/2, Expr). -spec let_float(expr_env(), fexpr()) -> fexpr(). -let_float(_, {'let', Ann, X, E, Body}) -> - pull_out_let({'let', Ann, X, {here, E}, Body}); -let_float(_, {proj, Ann, E, I}) -> - pull_out_let({proj, Ann, {here, E}, I}); -let_float(_, {set_proj, Ann, E, I, V}) -> - pull_out_let({set_proj, Ann, {here, E}, I, {here, V}}); -let_float(_, {op, Ann, Op, Es}) -> +let_float(_, {'let', FAnn, X, E, Body}) -> + pull_out_let({'let', FAnn, X, {here, E}, Body}); +let_float(_, {proj, FAnn, E, I}) -> + pull_out_let({proj, FAnn, {here, E}, I}); +let_float(_, {set_proj, FAnn, E, I, V}) -> + pull_out_let({set_proj, FAnn, {here, E}, I, {here, V}}); +let_float(_, {op, FAnn, Op, Es}) -> {Lets, Es1} = pull_out_let([{here, E} || E <- Es]), - let_bind(Lets, {op, Ann, Op, Es1}); + let_bind(Lets, {op, FAnn, Op, Es1}); let_float(_, E) -> E. -spec pull_out_let(fexpr() | [fexpr()]) -> fexpr() | {Lets, [fexpr()]} when @@ -1642,8 +1642,8 @@ constructor_form(Env, Expr) -> end; {set_proj, _, E, I, V} -> case constructor_form(Env, E) of - {tuple, Ann, Es} -> {tuple, Ann, setnth(I + 1, V, Es)}; - _ -> false + {tuple, FAnn, Es} -> {tuple, FAnn, setnth(I + 1, V, Es)}; + _ -> false end; {proj, _, E, I} -> case constructor_form(Env, E) of @@ -1664,10 +1664,10 @@ constructor_form(Env, Expr) -> drop_unused_lets(Expr) -> bottom_up(fun drop_unused_lets/2, Expr). -spec drop_unused_lets(expr_env(), fexpr()) -> fexpr(). -drop_unused_lets(_, {'let', Ann, X, E, Body} = Expr) -> +drop_unused_lets(_, {'let', FAnn, X, E, Body} = Expr) -> case {read_only(E), not lists:member(X, free_vars(Body))} of {true, true} -> Body; - {false, true} -> {'let', Ann, "_", E, Body}; + {false, true} -> {'let', FAnn, "_", E, Body}; _ -> Expr end; drop_unused_lets(_, Expr) -> Expr. @@ -1945,7 +1945,7 @@ free_vars(Expr) -> {proj, _, A, _} -> free_vars(A); {set_proj, _, A, _, B} -> free_vars([A, B]); {op, _, _, As} -> free_vars(As); - {'let', Ann, X, A, B} -> free_vars([A, {lam, Ann, [X], B}]); + {'let', FAnn, X, A, B} -> free_vars([A, {lam, FAnn, [X], B}]); {funcall, _, A, Bs} -> free_vars([A | Bs]); {set_state, _, _, A} -> free_vars(A); {get_state, _, _} -> []; @@ -2000,25 +2000,25 @@ bottom_up(F, Env, Expr) -> {lit, _, _} -> Expr; {nil, _} -> Expr; {var, _, _} -> Expr; - {def, Ann, D, Es} -> {def, Ann, D, [bottom_up(F, Env, E) || E <- Es]}; + {def, FAnn, D, Es} -> {def, FAnn, D, [bottom_up(F, Env, E) || E <- Es]}; {def_u, _, _, _} -> Expr; - {builtin, Ann, B, Es} -> {builtin, Ann, B, [bottom_up(F, Env, E) || E <- Es]}; + {builtin, FAnn, B, Es} -> {builtin, FAnn, B, [bottom_up(F, Env, E) || E <- Es]}; {builtin_u, _, _, _} -> Expr; {builtin_u, _, _, _, _} -> Expr; - {remote, Ann, ArgsT, RetT, Ct, Fun, Es} -> {remote, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun, [bottom_up(F, Env, E) || E <- Es]}; - {remote_u, Ann, ArgsT, RetT, Ct, Fun} -> {remote_u, Ann, ArgsT, RetT, bottom_up(F, Env, Ct), Fun}; - {con, Ann, Ar, I, Es} -> {con, Ann, Ar, I, [bottom_up(F, Env, E) || E <- Es]}; - {tuple, Ann, Es} -> {tuple, Ann, [bottom_up(F, Env, E) || E <- Es]}; - {proj, Ann, E, I} -> {proj, Ann, bottom_up(F, Env, E), I}; - {set_proj, Ann, R, I, E} -> {set_proj, Ann, bottom_up(F, Env, R), I, bottom_up(F, Env, E)}; - {op, Ann, Op, Es} -> {op, Ann, Op, [bottom_up(F, Env, E) || E <- Es]}; - {funcall, Ann, Fun, Es} -> {funcall, Ann, bottom_up(F, Env, Fun), [bottom_up(F, Env, E) || E <- Es]}; - {set_state, Ann, R, E} -> {set_state, Ann, R, bottom_up(F, Env, E)}; + {remote, FAnn, ArgsT, RetT, Ct, Fun, Es} -> {remote, FAnn, ArgsT, RetT, bottom_up(F, Env, Ct), Fun, [bottom_up(F, Env, E) || E <- Es]}; + {remote_u, FAnn, ArgsT, RetT, Ct, Fun} -> {remote_u, FAnn, ArgsT, RetT, bottom_up(F, Env, Ct), Fun}; + {con, FAnn, Ar, I, Es} -> {con, FAnn, Ar, I, [bottom_up(F, Env, E) || E <- Es]}; + {tuple, FAnn, Es} -> {tuple, FAnn, [bottom_up(F, Env, E) || E <- Es]}; + {proj, FAnn, E, I} -> {proj, FAnn, bottom_up(F, Env, E), I}; + {set_proj, FAnn, R, I, E} -> {set_proj, FAnn, bottom_up(F, Env, R), I, bottom_up(F, Env, E)}; + {op, FAnn, Op, Es} -> {op, FAnn, Op, [bottom_up(F, Env, E) || E <- Es]}; + {funcall, FAnn, Fun, Es} -> {funcall, FAnn, bottom_up(F, Env, Fun), [bottom_up(F, Env, E) || E <- Es]}; + {set_state, FAnn, R, E} -> {set_state, FAnn, R, bottom_up(F, Env, E)}; {get_state, _, _} -> Expr; - {closure, Ann, F, CEnv} -> {closure, Ann, F, bottom_up(F, Env, CEnv)}; - {switch, Ann, Split} -> {switch, Ann, bottom_up(F, Env, Split)}; - {lam, Ann, Xs, B} -> {lam, Ann, Xs, bottom_up(F, Env, B)}; - {'let', Ann, X, E, Body} -> + {closure, FAnn, F, CEnv} -> {closure, FAnn, F, bottom_up(F, Env, CEnv)}; + {switch, FAnn, Split} -> {switch, FAnn, bottom_up(F, Env, Split)}; + {lam, FAnn, Xs, B} -> {lam, FAnn, Xs, bottom_up(F, Env, B)}; + {'let', FAnn, X, E, Body} -> E1 = bottom_up(F, Env, E), %% Always freshen user variables to avoid shadowing issues. ShouldFreshen = fun(Y = "%" ++ _) -> maps:is_key(Y, Env); @@ -2027,10 +2027,10 @@ bottom_up(F, Env, Expr) -> true -> Z = fresh_name_save(X), Env1 = Env#{ Z => E1 }, - {'let', Ann, Z, E1, bottom_up(F, Env1, rename([{X, Z}], Body))}; + {'let', FAnn, Z, E1, bottom_up(F, Env1, rename([{X, Z}], Body))}; false -> Env1 = Env#{ X => E1 }, - {'let', Ann, X, E1, bottom_up(F, Env1, Body)} + {'let', FAnn, X, E1, bottom_up(F, Env1, Body)} end; {split, Type, X, Cases} -> {split, Type, X, [bottom_up(F, Env, Case) || Case <- Cases]}; {nosplit, E} -> {nosplit, bottom_up(F, Env, E)}; @@ -2057,32 +2057,32 @@ get_named_arg({named_arg_t, _, {id, _, Name}, _, Default}, Args) -> -spec rename(rename(), fexpr()) -> fexpr(). rename(Ren, Expr) -> case Expr of - {lit, _, _} -> Expr; - {nil, Ann} -> {nil, Ann}; - {var, Ann, X} -> {var, Ann, rename_var(Ren, X)}; - {def, Ann, D, Es} -> {def, Ann, D, [rename(Ren, E) || E <- Es]}; - {def_u, _, _, _} -> Expr; - {builtin, Ann, B, Es} -> {builtin, Ann, B, [rename(Ren, E) || E <- Es]}; - {builtin_u, _, _, _} -> Expr; - {builtin_u, _, _, _, _} -> Expr; - {remote, Ann, ArgsT, RetT, Ct, F, Es} -> {remote, Ann, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; - {remote_u, Ann, ArgsT, RetT, Ct, F} -> {remote_u, Ann, ArgsT, RetT, rename(Ren, Ct), F}; - {con, Ann, Ar, I, Es} -> {con, Ann, Ar, I, [rename(Ren, E) || E <- Es]}; - {tuple, Ann, Es} -> {tuple, Ann, [rename(Ren, E) || E <- Es]}; - {proj, Ann, E, I} -> {proj, Ann, rename(Ren, E), I}; - {set_proj, Ann, R, I, E} -> {set_proj, Ann, rename(Ren, R), I, rename(Ren, E)}; - {op, Ann, Op, Es} -> {op, Ann, Op, [rename(Ren, E) || E <- Es]}; - {funcall, Ann, Fun, Es} -> {funcall, Ann, rename(Ren, Fun), [rename(Ren, E) || E <- Es]}; - {set_state, Ann, R, E} -> {set_state, Ann, R, rename(Ren, E)}; - {get_state, _, _} -> Expr; - {closure, Ann, F, Env} -> {closure, Ann, F, rename(Ren, Env)}; - {switch, Ann, Split} -> {switch, Ann, rename_split(Ren, Split)}; - {lam, Ann, Xs, B} -> + {lit, _, _} -> Expr; + {nil, FAnn} -> {nil, FAnn}; + {var, FAnn, X} -> {var, FAnn, rename_var(Ren, X)}; + {def, FAnn, D, Es} -> {def, FAnn, D, [rename(Ren, E) || E <- Es]}; + {def_u, _, _, _} -> Expr; + {builtin, FAnn, B, Es} -> {builtin, FAnn, B, [rename(Ren, E) || E <- Es]}; + {builtin_u, _, _, _} -> Expr; + {builtin_u, _, _, _, _} -> Expr; + {remote, FAnn, ArgsT, RetT, Ct, F, Es} -> {remote, FAnn, ArgsT, RetT, rename(Ren, Ct), F, [rename(Ren, E) || E <- Es]}; + {remote_u, FAnn, ArgsT, RetT, Ct, F} -> {remote_u, FAnn, ArgsT, RetT, rename(Ren, Ct), F}; + {con, FAnn, Ar, I, Es} -> {con, FAnn, Ar, I, [rename(Ren, E) || E <- Es]}; + {tuple, FAnn, Es} -> {tuple, FAnn, [rename(Ren, E) || E <- Es]}; + {proj, FAnn, E, I} -> {proj, FAnn, rename(Ren, E), I}; + {set_proj, FAnn, R, I, E} -> {set_proj, FAnn, rename(Ren, R), I, rename(Ren, E)}; + {op, FAnn, Op, Es} -> {op, FAnn, Op, [rename(Ren, E) || E <- Es]}; + {funcall, FAnn, Fun, Es} -> {funcall, FAnn, rename(Ren, Fun), [rename(Ren, E) || E <- Es]}; + {set_state, FAnn, R, E} -> {set_state, FAnn, R, rename(Ren, E)}; + {get_state, _, _} -> Expr; + {closure, FAnn, F, Env} -> {closure, FAnn, F, rename(Ren, Env)}; + {switch, FAnn, Split} -> {switch, FAnn, rename_split(Ren, Split)}; + {lam, FAnn, Xs, B} -> {Zs, Ren1} = rename_bindings(Ren, Xs), - {lam, Ann, Zs, rename(Ren1, B)}; - {'let', Ann, X, E, Body} -> + {lam, FAnn, Zs, rename(Ren1, B)}; + {'let', FAnn, X, E, Body} -> {Z, Ren1} = rename_binding(Ren, X), - {'let', Ann, Z, rename(Ren, E), rename(Ren1, Body)} + {'let', FAnn, Z, rename(Ren, E), rename(Ren1, Body)} end. -spec rename_var(rename(), var_name()) -> var_name(). @@ -2121,15 +2121,15 @@ rename_fpat(Ren, {'::', P, Q}) -> {P1, Ren1} = rename_fpat(Ren, P), {Q1, Ren2} = rename_fpat(Ren1, Q), {{'::', P1, Q1}, Ren2}; -rename_fpat(Ren, {var, Ann, X}) -> +rename_fpat(Ren, {var, FAnn, X}) -> {Z, Ren1} = rename_binding(Ren, X), - {{var, Ann, Z}, Ren1}; -rename_fpat(Ren, {con, Ann, Ar, C, Ps}) -> + {{var, FAnn, Z}, Ren1}; +rename_fpat(Ren, {con, FAnn, Ar, C, Ps}) -> {Ps1, Ren1} = rename_fpats(Ren, Ps), - {{con, Ann, Ar, C, Ps1}, Ren1}; -rename_fpat(Ren, {tuple, Ann, Ps}) -> + {{con, FAnn, Ar, C, Ps1}, Ren1}; +rename_fpat(Ren, {tuple, FAnn, Ps}) -> {Ps1, Ren1} = rename_fpats(Ren, Ps), - {{tuple, Ann, Ps1}, Ren1}. + {{tuple, FAnn, Ps1}, Ren1}. -spec rename_spat(rename(), fsplit_pat()) -> {fsplit_pat(), rename()}. rename_spat(Ren, P = {bool, _}) -> {P, Ren}; @@ -2140,15 +2140,15 @@ rename_spat(Ren, {'::', X, Y}) -> {X1, Ren1} = rename_binding(Ren, X), {Y1, Ren2} = rename_binding(Ren1, Y), {{'::', X1, Y1}, Ren2}; -rename_spat(Ren, {var, Ann, X}) -> +rename_spat(Ren, {var, FAnn, X}) -> {Z, Ren1} = rename_binding(Ren, X), - {{var, Ann, Z}, Ren1}; -rename_spat(Ren, {con, Ann, Ar, C, Xs}) -> + {{var, FAnn, Z}, Ren1}; +rename_spat(Ren, {con, FAnn, Ar, C, Xs}) -> {Zs, Ren1} = rename_bindings(Ren, Xs), - {{con, Ann, Ar, C, Zs}, Ren1}; -rename_spat(Ren, {tuple, Ann, Xs}) -> + {{con, FAnn, Ar, C, Zs}, Ren1}; +rename_spat(Ren, {tuple, FAnn, Xs}) -> {Zs, Ren1} = rename_bindings(Ren, Xs), - {{tuple, Ann, Zs}, Ren1}; + {{tuple, FAnn, Zs}, Ren1}; rename_spat(Ren, {assign, X, P}) -> {X1, Ren1} = rename_binding(Ren, X), {P1, Ren2} = rename_binding(Ren1, P), @@ -2302,15 +2302,15 @@ pp_fexpr({def, _, Fun, Args}) -> pp_call(pp_fun_name(Fun), Args); pp_fexpr({con, _, _, I, []}) -> pp_beside(pp_text("C"), pp_int(I)); -pp_fexpr({con, Ann, _, I, Es}) -> - pp_beside(pp_fexpr({con, Ann, [], I, []}), - pp_fexpr({tuple, Ann, Es})); +pp_fexpr({con, FAnn, _, I, Es}) -> + pp_beside(pp_fexpr({con, FAnn, [], I, []}), + pp_fexpr({tuple, FAnn, Es})); pp_fexpr({tuple, _, Es}) -> pp_parens(pp_par(pp_punctuate(pp_text(","), [pp_fexpr(E) || E <- Es]))); pp_fexpr({proj, _, E, I}) -> pp_beside([pp_fexpr(E), pp_text("."), pp_int(I)]); -pp_fexpr({lam, Ann, Xs, A}) -> - pp_par([pp_fexpr({tuple, Ann, [{var, Ann, X} || X <- Xs]}), pp_text("=>"), +pp_fexpr({lam, FAnn, Xs, A}) -> + pp_par([pp_fexpr({tuple, FAnn, [{var, FAnn, X} || X <- Xs]}), pp_text("=>"), prettypr:nest(2, pp_fexpr(A))]); pp_fexpr({closure, _, Fun, ClEnv}) -> FVs = case ClEnv of @@ -2330,8 +2330,8 @@ pp_fexpr({op, _, Op, [A] = Args}) -> false -> pp_call(pp_text(Op), Args); true -> pp_parens(pp_par([pp_text(Op), pp_fexpr(A)])) end; -pp_fexpr({op, Ann, Op, As}) -> - pp_beside(pp_text(Op), pp_fexpr({tuple, Ann, As})); +pp_fexpr({op, FAnn, Op, As}) -> + pp_beside(pp_text(Op), pp_fexpr({tuple, FAnn, As})); pp_fexpr({'let', _, _, _, _} = Expr) -> Lets = fun Lets({'let', _, Y, C, D}) -> {Ls, E} = Lets(D), @@ -2346,8 +2346,8 @@ pp_fexpr({'let', _, _, _, _} = Expr) -> pp_fexpr(Body) ])); pp_fexpr({builtin_u, _, B, N}) -> pp_beside([pp_text(B), pp_text("/"), pp_text(N)]); -pp_fexpr({builtin_u, Ann, B, N, TypeArgs}) -> - pp_beside([pp_text(B), pp_text("@"), pp_fexpr({tuple, Ann, TypeArgs}), pp_text("/"), pp_text(N)]); +pp_fexpr({builtin_u, FAnn, B, N, TypeArgs}) -> + pp_beside([pp_text(B), pp_text("@"), pp_fexpr({tuple, FAnn, TypeArgs}), pp_text("/"), pp_text(N)]); pp_fexpr({builtin, _, B, As}) -> pp_call(pp_text(B), As); pp_fexpr({remote_u, _, ArgsT, RetT, Ct, Fun}) -> @@ -2406,13 +2406,13 @@ pp_case({'case', Pat, Split}) -> prettypr:nest(2, pp_split(Split))]). -spec pp_pat(fsplit_pat()) -> prettypr:document(). -pp_pat({tuple, Ann, Xs}) -> pp_fexpr({tuple, Ann, [{var, Ann, X} || X <- Xs]}); -pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, [], X}, {var, [], Xs}]}); -pp_pat({con, Ann, As, I, Xs}) -> pp_fexpr({con, Ann, As, I, [{var, [], X} || X <- Xs]}); -pp_pat({var, Ann, X}) -> pp_fexpr({var, Ann, X}); +pp_pat({tuple, FAnn, Xs}) -> pp_fexpr({tuple, FAnn, [{var, FAnn, X} || X <- Xs]}); +pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, [], X}, {var, [], Xs}]}); +pp_pat({con, FAnn, As, I, Xs}) -> pp_fexpr({con, FAnn, As, I, [{var, [], X} || X <- Xs]}); +pp_pat({var, FAnn, X}) -> pp_fexpr({var, FAnn, X}); pp_pat(P = {Tag, _}) when Tag == bool; Tag == int; Tag == string - -> pp_fexpr({lit, [], P}); -pp_pat(Pat) -> pp_fexpr(Pat). + -> pp_fexpr({lit, [], P}); +pp_pat(Pat) -> pp_fexpr(Pat). -spec is_infix(op()) -> boolean(). is_infix(Op) -> -- 2.30.2 From 354e49c5d3e72c4e7f909eb445b0e11e5048cf80 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 17 Nov 2022 17:15:17 +0300 Subject: [PATCH 30/92] Add line to fann() --- src/aeso_ast_to_fcode.erl | 4 ++-- src/aeso_fcode_to_fate.erl | 25 ++++++++++++++----------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index bb8cb53..d73619d 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -58,7 +58,7 @@ | {contract_code, string()} %% for CREATE, by name | {typerep, ftype()}. --type fann() :: [ {line, aeso_syntax:ann_line()} ]. +-type fann() :: [ {line, aeso_syntax:ann_line()} | {col, aeso_syntax:ann_col()} ]. -type fexpr() :: {lit, fann(), flit()} | {nil, fann()} @@ -389,7 +389,7 @@ to_fcode(Env, [{namespace, _, {con, _, Con}, Decls} | Code]) -> -spec to_fann(aeso_syntax:ann()) -> fann(). to_fann(Ann) -> - proplists:lookup_all(line, Ann). + proplists:lookup_all(line, Ann) ++ proplists:lookup_all(col, Ann). -spec get_fann(fexpr()) -> fann(). get_fann(FExpr) -> element(2, FExpr). diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index b227ff1..5b973a6 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -106,25 +106,25 @@ compile1(ChildContracts, FCode, SavedFreshNames, Options) -> {FateCode2, get_variables_registers(), DbglocMap}. -spec block_dbgloc_map(bcode()) -> DbglocMap when - DbglocMap :: #{integer() => integer()}. + DbglocMap :: #{integer() => {integer(), integer()}}. block_dbgloc_map(BB) -> block_dbgloc_map(BB, 0, maps:new()). -spec block_dbgloc_map(bcode(), integer(), DbglocMap) -> DbglocMap when - DbglocMap :: #{integer() => integer()}. + DbglocMap :: #{integer() => {integer(), integer()}}. block_dbgloc_map([], _, DbglocMap) -> DbglocMap; -block_dbgloc_map([{'DBGLOC', Line} | Rest], Index, DbglocMap) -> - block_dbgloc_map(Rest, Index, maps:put(Index, Line, DbglocMap)); +block_dbgloc_map([{'DBGLOC', Line, Col} | Rest], Index, DbglocMap) -> + block_dbgloc_map(Rest, Index, maps:put(Index, {Line, Col}, DbglocMap)); block_dbgloc_map([_ | Rest], Index, DbglocMap) -> block_dbgloc_map(Rest, Index + 1, DbglocMap). -spec remove_dbgloc(aeb_fate_code:fcode()) -> {aeb_fate_code:fcode(), DbglocMap} when - DbglocMap :: #{integer() => integer()}. + DbglocMap :: #{integer() => {integer(), integer()}}. remove_dbgloc(FateCode) -> RemoveDbglocFromBBs = fun(_, BB) -> - IsDbg = fun({'DBGLOC', _}) -> false; - (_) -> true + IsDbg = fun({'DBGLOC', _, _}) -> false; + (_) -> true end, lists:filter(IsDbg, BB) end, @@ -806,9 +806,12 @@ dbgloc(Env, Ann) -> case proplists:get_value(debug_info, Env#env.options, false) of false -> []; true -> - case proplists:get_value(line, Ann) of - undefined -> []; - Line -> [{'DBGLOC', Line}] + Line = proplists:get_value(line, Ann), + Col = proplists:get_value(col, Ann), + case {Line, Col} of + {undefined, _} -> []; + {_, undefined} -> []; + {Line, Col} -> [{'DBGLOC', Line, Col}] end end. @@ -947,7 +950,7 @@ attributes(I) -> loop -> Impure(pc, []); switch_body -> Pure(none, []); 'RETURN' -> Impure(pc, []); - {'DBGLOC', _} -> Impure(pc, []); + {'DBGLOC', _, _} -> Impure(pc, []); {'RETURNR', A} -> Impure(pc, A); {'CALL', A} -> Impure(?a, [A]); {'CALL_R', A, _, B, C, D} -> Impure(?a, [A, B, C, D]); -- 2.30.2 From db3f63529dece486aa219293f47a1066fce9544f Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 17 Nov 2022 17:18:35 +0300 Subject: [PATCH 31/92] Change attributes for DBGLOC instruction --- src/aeso_fcode_to_fate.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 5b973a6..e971bb5 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -950,7 +950,7 @@ attributes(I) -> loop -> Impure(pc, []); switch_body -> Pure(none, []); 'RETURN' -> Impure(pc, []); - {'DBGLOC', _, _} -> Impure(pc, []); + {'DBGLOC', _, _} -> Pure(none, []); {'RETURNR', A} -> Impure(pc, A); {'CALL', A} -> Impure(?a, [A]); {'CALL_R', A, _, B, C, D} -> Impure(?a, [A, B, C, D]); -- 2.30.2 From eb16d2f77bcdca84349a30d0ff4319d837f7c590 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 17 Nov 2022 17:23:42 +0300 Subject: [PATCH 32/92] Add file to fann() --- src/aeso_ast_to_fcode.erl | 7 +++++-- src/aeso_fcode_to_fate.erl | 13 +++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index d73619d..0eab963 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -58,7 +58,7 @@ | {contract_code, string()} %% for CREATE, by name | {typerep, ftype()}. --type fann() :: [ {line, aeso_syntax:ann_line()} | {col, aeso_syntax:ann_col()} ]. +-type fann() :: [ {file, string() | no_file} | {line, aeso_syntax:ann_line()} | {col, aeso_syntax:ann_col()} ]. -type fexpr() :: {lit, fann(), flit()} | {nil, fann()} @@ -389,7 +389,10 @@ to_fcode(Env, [{namespace, _, {con, _, Con}, Decls} | Code]) -> -spec to_fann(aeso_syntax:ann()) -> fann(). to_fann(Ann) -> - proplists:lookup_all(line, Ann) ++ proplists:lookup_all(col, Ann). + File = proplists:lookup_all(file, Ann), + Line = proplists:lookup_all(line, Ann), + Col = proplists:lookup_all(col, Ann), + lists:flatten([File, Line, Col]). -spec get_fann(fexpr()) -> fann(). get_fann(FExpr) -> element(2, FExpr). diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index e971bb5..83701de 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -113,8 +113,8 @@ block_dbgloc_map(BB) -> block_dbgloc_map(BB, 0, maps:new()). DbglocMap :: #{integer() => {integer(), integer()}}. block_dbgloc_map([], _, DbglocMap) -> DbglocMap; -block_dbgloc_map([{'DBGLOC', Line, Col} | Rest], Index, DbglocMap) -> - block_dbgloc_map(Rest, Index, maps:put(Index, {Line, Col}, DbglocMap)); +block_dbgloc_map([{'DBGLOC', File, Line, Col} | Rest], Index, DbglocMap) -> + block_dbgloc_map(Rest, Index, maps:put(Index, {File, Line, Col}, DbglocMap)); block_dbgloc_map([_ | Rest], Index, DbglocMap) -> block_dbgloc_map(Rest, Index + 1, DbglocMap). @@ -123,8 +123,8 @@ block_dbgloc_map([_ | Rest], Index, DbglocMap) -> remove_dbgloc(FateCode) -> RemoveDbglocFromBBs = fun(_, BB) -> - IsDbg = fun({'DBGLOC', _, _}) -> false; - (_) -> true + IsDbg = fun({'DBGLOC', _, _, _}) -> false; + (_) -> true end, lists:filter(IsDbg, BB) end, @@ -806,12 +806,13 @@ dbgloc(Env, Ann) -> case proplists:get_value(debug_info, Env#env.options, false) of false -> []; true -> + File = proplists:get_value(file, Ann), Line = proplists:get_value(line, Ann), Col = proplists:get_value(col, Ann), case {Line, Col} of {undefined, _} -> []; {_, undefined} -> []; - {Line, Col} -> [{'DBGLOC', Line, Col}] + {Line, Col} -> [{'DBGLOC', File, Line, Col}] end end. @@ -950,7 +951,7 @@ attributes(I) -> loop -> Impure(pc, []); switch_body -> Pure(none, []); 'RETURN' -> Impure(pc, []); - {'DBGLOC', _, _} -> Pure(none, []); + {'DBGLOC', _, _, _} -> Pure(none, []); {'RETURNR', A} -> Impure(pc, A); {'CALL', A} -> Impure(?a, [A]); {'CALL_R', A, _, B, C, D} -> Impure(?a, [A, B, C, D]); -- 2.30.2 From f6beec0a7ca37a1de7e3faf4e850a3dcaf4d197b Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 17 Nov 2022 17:26:22 +0300 Subject: [PATCH 33/92] Add file to aeso_syntax:ann() --- src/aeso_ast_to_fcode.erl | 2 +- src/aeso_syntax.erl | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 0eab963..6264b2c 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -58,7 +58,7 @@ | {contract_code, string()} %% for CREATE, by name | {typerep, ftype()}. --type fann() :: [ {file, string() | no_file} | {line, aeso_syntax:ann_line()} | {col, aeso_syntax:ann_col()} ]. +-type fann() :: [ {file, aeso_syntax:ann_file()} | {line, aeso_syntax:ann_line()} | {col, aeso_syntax:ann_col()} ]. -type fexpr() :: {lit, fann(), flit()} | {nil, fann()} diff --git a/src/aeso_syntax.erl b/src/aeso_syntax.erl index f1c7f99..0ff9f5e 100644 --- a/src/aeso_syntax.erl +++ b/src/aeso_syntax.erl @@ -10,7 +10,7 @@ -export([get_ann/1, get_ann/2, get_ann/3, set_ann/2, qualify/2]). --export_type([ann_line/0, ann_col/0, ann_origin/0, ann_format/0, ann/0]). +-export_type([ann_file/0, ann_line/0, ann_col/0, ann_origin/0, ann_format/0, ann/0]). -export_type([name/0, id/0, con/0, qid/0, qcon/0, tvar/0, op/0]). -export_type([bin_op/0, un_op/0]). -export_type([decl/0, letbind/0, typedef/0, pragma/0, fundecl/0]). @@ -24,8 +24,9 @@ -type ann_col() :: integer(). -type ann_origin() :: system | user. -type ann_format() :: '?:' | hex | infix | prefix | elif. +-type ann_file() :: string() | no_file. --type ann() :: [ {line, ann_line()} | {col, ann_col()} | {format, ann_format()} | {origin, ann_origin()} +-type ann() :: [ {file, ann_file()} | {line, ann_line()} | {col, ann_col()} | {format, ann_format()} | {origin, ann_origin()} | stateful | private | payable | main | interface | entrypoint]. -type name() :: string(). -- 2.30.2 From 9ddd29d63ad6b7d2d489d7c87e982fd118c1b59d Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 17 Nov 2022 17:32:51 +0300 Subject: [PATCH 34/92] Fix dialyzer warning --- src/aeso_fcode_to_fate.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 83701de..7d041aa 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -106,11 +106,11 @@ compile1(ChildContracts, FCode, SavedFreshNames, Options) -> {FateCode2, get_variables_registers(), DbglocMap}. -spec block_dbgloc_map(bcode()) -> DbglocMap when - DbglocMap :: #{integer() => {integer(), integer()}}. + DbglocMap :: #{integer() => {aeso_syntax:ann_file(), aeso_syntax:ann_line(), aeso_syntax:ann_col()}}. block_dbgloc_map(BB) -> block_dbgloc_map(BB, 0, maps:new()). -spec block_dbgloc_map(bcode(), integer(), DbglocMap) -> DbglocMap when - DbglocMap :: #{integer() => {integer(), integer()}}. + DbglocMap :: #{integer() => {aeso_syntax:ann_file(), aeso_syntax:ann_line(), aeso_syntax:ann_col()}}. block_dbgloc_map([], _, DbglocMap) -> DbglocMap; block_dbgloc_map([{'DBGLOC', File, Line, Col} | Rest], Index, DbglocMap) -> @@ -119,7 +119,7 @@ block_dbgloc_map([_ | Rest], Index, DbglocMap) -> block_dbgloc_map(Rest, Index + 1, DbglocMap). -spec remove_dbgloc(aeb_fate_code:fcode()) -> {aeb_fate_code:fcode(), DbglocMap} when - DbglocMap :: #{integer() => {integer(), integer()}}. + DbglocMap :: #{integer() => {aeso_syntax:ann_file(), aeso_syntax:ann_line(), aeso_syntax:ann_col()}}. remove_dbgloc(FateCode) -> RemoveDbglocFromBBs = fun(_, BB) -> -- 2.30.2 From a752fa5b48cbb79568e0fe9a54d07ba353c485e7 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 19 Nov 2022 12:38:53 +0300 Subject: [PATCH 35/92] Remove fann() from fsplit_pat() and fpat() --- src/aeso_ast_to_fcode.erl | 188 +++++++++++++++++++------------------ src/aeso_fcode_to_fate.erl | 4 +- 2 files changed, 98 insertions(+), 94 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 6264b2c..280ef80 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -91,14 +91,14 @@ -type fcase() :: {'case', fsplit_pat(), fsplit()}. --type fsplit_pat() :: {var, fann(), var_name()} +-type fsplit_pat() :: {var, var_name()} | {bool, false | true} | {int, integer()} | {string, binary()} - | {nil, fann()} + | nil | {'::', var_name(), var_name()} - | {con, fann(), arities(), tag(), [var_name()]} - | {tuple, fann(), [var_name()]} + | {con, arities(), tag(), [var_name()]} + | {tuple, [var_name()]} | {assign, var_name(), var_name()}. -type ftype() :: integer @@ -839,6 +839,10 @@ make_if_no_else(Cond, Then) -> make_tuple([E]) -> E; make_tuple(Es) -> {tuple, [], Es}. +-spec make_tuple_fpat([fpat()]) -> fpat(). +make_tuple_fpat([P]) -> P; +make_tuple_fpat(Ps) -> {tuple, Ps}. + -spec strip_singleton_tuples(ftype()) -> ftype(). strip_singleton_tuples({tuple, _, [T]}) -> strip_singleton_tuples(T); strip_singleton_tuples(T) -> T. @@ -864,14 +868,14 @@ alts_to_fcode(Env, Type, X, Alts, Switch) -> %% Intermediate format before case trees (fcase() and fsplit()). -type falt() :: {'case', [fpat()], fexpr()}. --type fpat() :: {var, fann(), var_name()} +-type fpat() :: {var, var_name()} | {bool, false | true} | {int, integer()} | {string, binary()} - | {nil, fann()} + | nil | {'::', fpat(), fpat()} - | {tuple, fann(), [fpat()]} - | {con, fann(), arities(), tag(), [fpat()]} + | {tuple, [fpat()]} + | {con, arities(), tag(), [fpat()]} | {assign, fpat(), fpat()}. -spec remove_guards(env(), [aeso_syntax:alt()], aeso_syntax:expr()) -> [falt()]. @@ -918,7 +922,7 @@ split_tree(Env, Vars, Alts = [{'case', Pats, Body} | _]) -> case next_split(Pats) of false -> Xs = [ X || {X, _} <- Vars ], - Ys = [ Y || {var, _, Y} <- Pats ], + Ys = [ Y || {var, Y} <- Pats ], Ren = [ {Y, X} || {Y, X} <- lists:zip(Ys, Xs), X /= Y, Y /= "_" ], %% TODO: Unreachable clauses error {nosplit, rename(Ren, Body)}; @@ -926,7 +930,7 @@ split_tree(Env, Vars, Alts = [{'case', Pats, Body} | _]) -> {Vars0, [{X, Type} | Vars1]} = lists:split(I - 1, Vars), Type1 = strip_singleton_tuples(Type), SAlts = merge_alts(I, X, [ split_alt(I, A) || A <- Alts ]), - MakeCase = fun({var, FAnn, Z}, Split) -> {'case', {var, FAnn, "_"}, rename_split([{Z, X}], Split)}; + MakeCase = fun({var, Z}, Split) -> {'case', {var, "_"}, rename_split([{Z, X}], Split)}; (SPat, Split) -> {'case', SPat, Split} end, Cases = [ MakeCase(SPat, split_tree(Env, Vars0 ++ split_vars(SPat, Type1) ++ Vars1, FAlts)) || {SPat, FAlts} <- SAlts ], @@ -948,18 +952,18 @@ merge_alts(I, X, Alts, Alts1) -> when Alts :: [{fsplit_pat(), [falt()]}]. merge_alt(_, _, {P, A}, []) -> [{P, [A]}]; merge_alt(I, X, {P, A}, [{Q, As} | Rest]) -> - Match = fun({var, _, _}, {var, _, _}) -> match; - ({tuple, _, _}, {tuple, _, _}) -> match; - ({bool, B}, {bool, B}) -> match; - ({int, N}, {int, N}) -> match; - ({string, S}, {string, S}) -> match; - ({nil, []}, {nil, []}) -> match; - ({'::', _, _}, {'::', _, _}) -> match; - ({con, _, _, C, _}, {con, _, _, C, _}) -> match; - ({con, _, _, _, _}, {con, _, _, _, _}) -> mismatch; - ({var, _, _}, _) -> expand; - (_, {var, _, _}) -> insert; - (_, _) -> mismatch + Match = fun({var, _}, {var, _}) -> match; + ({tuple, _}, {tuple, _}) -> match; + ({bool, B}, {bool, B}) -> match; + ({int, N}, {int, N}) -> match; + ({string, S}, {string, S}) -> match; + (nil, nil) -> match; + ({'::', _, _}, {'::', _, _}) -> match; + ({con, _, C, _}, {con, _, C, _}) -> match; + ({con, _, _, _}, {con, _, _, _}) -> mismatch; + ({var, _}, _) -> expand; + (_, {var, _}) -> insert; + (_, _) -> mismatch end, case Match(P, Q) of match -> [{Q, [A | As]} | Rest]; @@ -972,18 +976,18 @@ merge_alt(I, X, {P, A}, [{Q, As} | Rest]) -> -spec expand(integer(), var_name(), fsplit_pat(), fsplit_pat(), falt()) -> term(). expand(I, X, P, Q, Case = {'case', Ps, E}) -> - {Ps0, [{var, _, Y} | Ps1]} = lists:split(I - 1, Ps), + {Ps0, [{var, Y} | Ps1]} = lists:split(I - 1, Ps), {Ps0r, Ren1} = rename_fpats([{Y, X} || Y /= X], Ps0), {Ps1r, Ren2} = rename_fpats(Ren1, Ps1), E1 = rename(Ren2, E), - Splice = fun(N) -> Ps0r ++ lists:duplicate(N, {var, [], "_"}) ++ Ps1r end, - Type = fun({tuple, _, Xs}) -> {tuple, length(Xs)}; - ({bool, _}) -> bool; - ({int, _}) -> int; - ({string, _}) -> string; - ({nil, _}) -> list; - ({'::', _, _}) -> list; - ({con, _, As, _, _}) -> {variant, As} + Splice = fun(N) -> Ps0r ++ lists:duplicate(N, {var, "_"}) ++ Ps1r end, + Type = fun({tuple, Xs}) -> {tuple, length(Xs)}; + ({bool, _}) -> bool; + ({int, _}) -> int; + ({string, _}) -> string; + (nil) -> list; + ({'::', _, _}) -> list; + ({con, As, _, _}) -> {variant, As} end, MkCase = fun(Pat, Vars) -> {Pat, {'case', Splice(Vars), E1}} end, case Type(Q) of @@ -991,8 +995,8 @@ expand(I, X, P, Q, Case = {'case', Ps, E}) -> bool -> {[MkCase({bool, B}, 0) || B <- [false, true]], []}; int -> {[MkCase(Q, 0)], [{P, Case}]}; string -> {[MkCase(Q, 0)], [{P, Case}]}; - list -> {[MkCase({nil, []}, 0), MkCase({'::', fresh_name(), fresh_name()}, 2)], []}; - {variant, As} -> {[MkCase({con, [], As, C - 1, [fresh_name() || _ <- lists:seq(1, Ar)]}, Ar) + list -> {[MkCase(nil, 0), MkCase({'::', fresh_name(), fresh_name()}, 2)], []}; + {variant, As} -> {[MkCase({con, As, C - 1, [fresh_name() || _ <- lists:seq(1, Ar)]}, Ar) || {C, Ar} <- indexed(As)], []} end. @@ -1003,37 +1007,37 @@ split_alt(I, {'case', Pats, Body}) -> {SPat, {'case', Pats0 ++ InnerPats ++ Pats1, Body}}. -spec split_pat(fpat()) -> {fsplit_pat(), [fpat()]}. -split_pat(P = {var, FAnn, _}) -> {{var, FAnn, fresh_name()}, [P]}; -split_pat({bool, B}) -> {{bool, B}, []}; -split_pat({int, N}) -> {{int, N}, []}; -split_pat({string, N}) -> {{string, N}, []}; -split_pat({nil, FAnn}) -> {{nil, FAnn}, []}; +split_pat(P = {var, _}) -> {{var, fresh_name()}, [P]}; +split_pat({bool, B}) -> {{bool, B}, []}; +split_pat({int, N}) -> {{int, N}, []}; +split_pat({string, N}) -> {{string, N}, []}; +split_pat(nil) -> {nil, []}; split_pat({'::', P, Q}) -> {{'::', fresh_name(), fresh_name()}, [P, Q]}; -split_pat({con, FAnn, As, I, Pats}) -> +split_pat({con, As, I, Pats}) -> Xs = [fresh_name() || _ <- Pats], - {{con, FAnn, As, I, Xs}, Pats}; -split_pat({assign, X = {var, _, _}, P}) -> + {{con, As, I, Xs}, Pats}; +split_pat({assign, X = {var, _}, P}) -> {{assign, fresh_name(), fresh_name()}, [X, P]}; -split_pat({tuple, FAnn, Pats}) -> +split_pat({tuple, Pats}) -> Xs = [fresh_name() || _ <- Pats], - {{tuple, FAnn, Xs}, Pats}. + {{tuple, Xs}, Pats}. -spec split_vars(fsplit_pat(), ftype()) -> [{var_name(), ftype()}]. split_vars({bool, _}, boolean) -> []; split_vars({int, _}, integer) -> []; split_vars({string, _}, string) -> []; -split_vars({nil, _}, {list, _}) -> []; +split_vars(nil, {list, _}) -> []; split_vars({'::', X, Xs}, {list, T}) -> [{X, T}, {Xs, {list, T}}]; split_vars({assign, X, P}, T) -> [{X, T}, {P, T}]; -split_vars({con, _, _, I, Xs}, {variant, Cons}) -> +split_vars({con, _, I, Xs}, {variant, Cons}) -> lists:zip(Xs, lists:nth(I + 1, Cons)); -split_vars({tuple, _, Xs}, {tuple, Ts}) -> +split_vars({tuple, Xs}, {tuple, Ts}) -> lists:zip(Xs, Ts); -split_vars({var, _, X}, T) -> [{X, T}]. +split_vars({var, X}, T) -> [{X, T}]. -spec next_split([fpat()]) -> integer() | false. next_split(Pats) -> - IsVar = fun({var, _, _}) -> true; (_) -> false end, + IsVar = fun({var, _}) -> true; (_) -> false end, case [ I || {I, P} <- indexed(Pats), not IsVar(P) ] of [] -> false; [I | _] -> I @@ -1052,15 +1056,15 @@ pat_to_fcode(Env, Pat) -> pat_to_fcode(Env, no_type, Pat). -spec pat_to_fcode(env(), aeso_syntax:type() | no_type, aeso_syntax:pat()) -> fpat(). -pat_to_fcode(_Env, _Type, {id, Ann, X}) -> {var, to_fann(Ann), X}; -pat_to_fcode(Env, _Type, {C, Ann, _} = Con) when C == con; C == qcon -> +pat_to_fcode(_Env, _Type, {id, _, X}) -> {var, X}; +pat_to_fcode(Env, _Type, {C, _, _} = Con) when C == con; C == qcon -> #con_tag{tag = I, arities = As} = lookup_con(Env, Con), - {con, to_fann(Ann), As, I, []}; -pat_to_fcode(Env, _Type, {app, _, {typed, _, {C, Ann, _} = Con, _}, Pats}) when C == con; C == qcon -> + {con, As, I, []}; +pat_to_fcode(Env, _Type, {app, _, {typed, _, {C, _, _} = Con, _}, Pats}) when C == con; C == qcon -> #con_tag{tag = I, arities = As} = lookup_con(Env, Con), - {con, to_fann(Ann), As, I, [pat_to_fcode(Env, Pat) || Pat <- Pats]}; + {con, As, I, [pat_to_fcode(Env, Pat) || Pat <- Pats]}; pat_to_fcode(Env, _Type, {tuple, _, Pats}) -> - make_tuple([ pat_to_fcode(Env, Pat) || Pat <- Pats ]); + make_tuple_fpat([ pat_to_fcode(Env, Pat) || Pat <- Pats ]); pat_to_fcode(_Env, _Type, {bool, _, B}) -> {bool, B}; pat_to_fcode(_Env, _Type, {int, _, N}) -> {int, N}; pat_to_fcode(_Env, _Type, {char, _, N}) -> {int, N}; @@ -1068,7 +1072,7 @@ pat_to_fcode(_Env, _Type, {string, _, N}) -> {string, N}; pat_to_fcode(Env, _Type, {list, _, Ps}) -> lists:foldr(fun(P, Qs) -> {'::', pat_to_fcode(Env, P), Qs} - end, {nil, []}, Ps); + end, nil, Ps); pat_to_fcode(Env, _Type, {app, _, {'::', _}, [P, Q]}) -> {'::', pat_to_fcode(Env, P), pat_to_fcode(Env, Q)}; pat_to_fcode(Env, {record_t, Fields}, {record, _, FieldPats}) -> @@ -1078,7 +1082,7 @@ pat_to_fcode(Env, {record_t, Fields}, {record, _, FieldPats}) -> {set, Pat} -> Pat %% {upd, _, _} is impossible in patterns end end, - make_tuple([pat_to_fcode(Env, FieldPat(Field)) + make_tuple_fpat([pat_to_fcode(Env, FieldPat(Field)) || Field <- Fields]); pat_to_fcode(Env, _Type, {letpat, _, Id = {typed, _, {id, _, _}, _}, Pattern}) -> {assign, pat_to_fcode(Env, Id), pat_to_fcode(Env, Pattern)}; @@ -1590,7 +1594,7 @@ get_catchalls(Alts) -> -spec add_catchalls([fcase()], [fcase()]) -> [fcase()]. add_catchalls(Alts, []) -> Alts; add_catchalls(Alts, Catchalls) -> - case lists:splitwith(fun({'case', {var, _, _}, _}) -> false; (_) -> true end, + case lists:splitwith(fun({'case', {var, _}, _}) -> false; (_) -> true end, Alts) of {Alts1, [C]} -> Alts1 ++ [nest_catchalls([C | Catchalls])]; {_, []} -> Alts ++ [nest_catchalls(Catchalls)] @@ -1598,8 +1602,8 @@ add_catchalls(Alts, Catchalls) -> end. -spec nest_catchalls([fcase()]) -> fcase(). -nest_catchalls([C = {'case', {var, _, _}, {nosplit, _}} | _]) -> C; -nest_catchalls([{'case', P = {var, _, _}, {split, Type, X, Alts}} | Catchalls]) -> +nest_catchalls([C = {'case', {var, _}, {nosplit, _}} | _]) -> C; +nest_catchalls([{'case', P = {var, _}, {split, Type, X, Alts}} | Catchalls]) -> {'case', P, {split, Type, X, add_catchalls(Alts, Catchalls)}}. -spec simpl_switch(expr_env(), [fcase()], fsplit()) -> fexpr() | nomatch. @@ -1626,14 +1630,14 @@ simpl_case(Env, E, [{'case', Pat, Body} | Alts]) -> end. -spec match_pat(fsplit_pat(), fexpr()) -> false | [{var_name(), fexpr()}]. -match_pat({tuple, _, Xs}, {tuple, _, Es}) -> lists:zip(Xs, Es); -match_pat({con, _, _, C, Xs}, {con, _, _, C, Es}) -> lists:zip(Xs, Es); -match_pat(L, {lit, _, L}) -> []; -match_pat({nil, _}, {nil, _}) -> []; -match_pat({'::', X, Y}, {op, _, '::', [A, B]}) -> [{X, A}, {Y, B}]; -match_pat({var, _, X}, E) -> [{X, E}]; -match_pat({assign, X, P}, E) -> [{X, E}, {P, E}]; -match_pat(_, _) -> false. +match_pat({tuple, Xs}, {tuple, _, Es}) -> lists:zip(Xs, Es); +match_pat({con, _, C, Xs}, {con, _, _, C, Es}) -> lists:zip(Xs, Es); +match_pat(L, {lit, _, L}) -> []; +match_pat(nil, {nil, _}) -> []; +match_pat({'::', X, Y}, {op, _, '::', [A, B]}) -> [{X, A}, {Y, B}]; +match_pat({var, X}, E) -> [{X, E}]; +match_pat({assign, X, P}, E) -> [{X, E}, {P, E}]; +match_pat(_, _) -> false. -spec constructor_form(expr_env(), fexpr()) -> fexpr() | false. constructor_form(Env, Expr) -> @@ -1907,26 +1911,26 @@ fresh_name(Prefix) -> lists:concat([Prefix, N]). -spec pat_vars(fpat()) -> [var_name()]. -pat_vars({var, _, X}) -> [X || X /= "_"]; +pat_vars({var, X}) -> [X || X /= "_"]; pat_vars({bool, _}) -> []; pat_vars({int, _}) -> []; pat_vars({string, _}) -> []; -pat_vars({nil, _}) -> []; +pat_vars(nil) -> []; pat_vars({'::', P, Q}) -> pat_vars(P) ++ pat_vars(Q); -pat_vars({tuple, _, Ps}) -> pat_vars(Ps); -pat_vars({con, _, _, _, Ps}) -> pat_vars(Ps); +pat_vars({tuple, Ps}) -> pat_vars(Ps); +pat_vars({con, _, _, Ps}) -> pat_vars(Ps); pat_vars({assign, X, P}) -> pat_vars(X) ++ pat_vars(P); pat_vars(Ps) when is_list(Ps) -> [X || P <- Ps, X <- pat_vars(P)]. -spec fsplit_pat_vars(fsplit_pat()) -> [var_name()]. -fsplit_pat_vars({var, _, X}) -> [X || X /= "_"]; +fsplit_pat_vars({var, X}) -> [X || X /= "_"]; fsplit_pat_vars({bool, _}) -> []; fsplit_pat_vars({int, _}) -> []; fsplit_pat_vars({string, _}) -> []; -fsplit_pat_vars({nil, _}) -> []; +fsplit_pat_vars(nil) -> []; fsplit_pat_vars({'::', P, Q}) -> [P, Q]; -fsplit_pat_vars({tuple, _, Ps}) -> Ps; -fsplit_pat_vars({con, _, _, _, Ps}) -> Ps. +fsplit_pat_vars({tuple, Ps}) -> Ps; +fsplit_pat_vars({con, _, _, Ps}) -> Ps. -spec free_vars(fexpr() | [fexpr()]) -> [var_name()]. free_vars(Xs) when is_list(Xs) -> @@ -2119,39 +2123,39 @@ rename_fpats(Ren, [P | Ps]) -> rename_fpat(Ren, P = {bool, _}) -> {P, Ren}; rename_fpat(Ren, P = {int, _}) -> {P, Ren}; rename_fpat(Ren, P = {string, _}) -> {P, Ren}; -rename_fpat(Ren, P = {nil, _}) -> {P, Ren}; +rename_fpat(Ren, P = nil) -> {P, Ren}; rename_fpat(Ren, {'::', P, Q}) -> {P1, Ren1} = rename_fpat(Ren, P), {Q1, Ren2} = rename_fpat(Ren1, Q), {{'::', P1, Q1}, Ren2}; -rename_fpat(Ren, {var, FAnn, X}) -> +rename_fpat(Ren, {var, X}) -> {Z, Ren1} = rename_binding(Ren, X), - {{var, FAnn, Z}, Ren1}; -rename_fpat(Ren, {con, FAnn, Ar, C, Ps}) -> + {{var, Z}, Ren1}; +rename_fpat(Ren, {con, Ar, C, Ps}) -> {Ps1, Ren1} = rename_fpats(Ren, Ps), - {{con, FAnn, Ar, C, Ps1}, Ren1}; -rename_fpat(Ren, {tuple, FAnn, Ps}) -> + {{con, Ar, C, Ps1}, Ren1}; +rename_fpat(Ren, {tuple, Ps}) -> {Ps1, Ren1} = rename_fpats(Ren, Ps), - {{tuple, FAnn, Ps1}, Ren1}. + {{tuple, Ps1}, Ren1}. -spec rename_spat(rename(), fsplit_pat()) -> {fsplit_pat(), rename()}. rename_spat(Ren, P = {bool, _}) -> {P, Ren}; rename_spat(Ren, P = {int, _}) -> {P, Ren}; rename_spat(Ren, P = {string, _}) -> {P, Ren}; -rename_spat(Ren, P = {nil, _}) -> {P, Ren}; +rename_spat(Ren, P = nil) -> {P, Ren}; rename_spat(Ren, {'::', X, Y}) -> {X1, Ren1} = rename_binding(Ren, X), {Y1, Ren2} = rename_binding(Ren1, Y), {{'::', X1, Y1}, Ren2}; -rename_spat(Ren, {var, FAnn, X}) -> +rename_spat(Ren, {var, X}) -> {Z, Ren1} = rename_binding(Ren, X), - {{var, FAnn, Z}, Ren1}; -rename_spat(Ren, {con, FAnn, Ar, C, Xs}) -> + {{var, Z}, Ren1}; +rename_spat(Ren, {con, Ar, C, Xs}) -> {Zs, Ren1} = rename_bindings(Ren, Xs), - {{con, FAnn, Ar, C, Zs}, Ren1}; -rename_spat(Ren, {tuple, FAnn, Xs}) -> + {{con, Ar, C, Zs}, Ren1}; +rename_spat(Ren, {tuple, Xs}) -> {Zs, Ren1} = rename_bindings(Ren, Xs), - {{tuple, FAnn, Zs}, Ren1}; + {{tuple, Zs}, Ren1}; rename_spat(Ren, {assign, X, P}) -> {X1, Ren1} = rename_binding(Ren, X), {P1, Ren2} = rename_binding(Ren1, P), @@ -2409,10 +2413,10 @@ pp_case({'case', Pat, Split}) -> prettypr:nest(2, pp_split(Split))]). -spec pp_pat(fsplit_pat()) -> prettypr:document(). -pp_pat({tuple, FAnn, Xs}) -> pp_fexpr({tuple, FAnn, [{var, FAnn, X} || X <- Xs]}); +pp_pat({tuple, Xs}) -> pp_fexpr({tuple, [], [{var, X} || X <- Xs]}); pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, [], X}, {var, [], Xs}]}); -pp_pat({con, FAnn, As, I, Xs}) -> pp_fexpr({con, FAnn, As, I, [{var, [], X} || X <- Xs]}); -pp_pat({var, FAnn, X}) -> pp_fexpr({var, FAnn, X}); +pp_pat({con, As, I, Xs}) -> pp_fexpr({con, [], As, I, [{var, [], X} || X <- Xs]}); +pp_pat({var, X}) -> pp_fexpr({var, [], X}); pp_pat(P = {Tag, _}) when Tag == bool; Tag == int; Tag == string -> pp_fexpr({lit, [], P}); pp_pat(Pat) -> pp_fexpr(Pat). diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 7d041aa..df9778b 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -507,7 +507,7 @@ split_to_scode(Env, {split, {list, _}, X, Alts}) -> GetAlt = fun(P) -> case [C || C = {'case', Pat, _} <- Alts1, Pat == P orelse is_tuple(Pat) andalso element(1, Pat) == P] of [] -> missing; - [{'case', {nil, _}, S} | _] -> split_to_scode(Env, S); + [{'case', nil, S} | _] -> split_to_scode(Env, S); [{'case', {'::', Y, Z}, S} | _] -> {I, Env1} = bind_local(Y, Env), {J, Env2} = bind_local(Z, Env1), @@ -558,7 +558,7 @@ literal_split_to_scode(Env, Type, Arg, [{'case', Lit, Body} | Alts], Def) when T catchall_to_scode(Env, X, Alts) -> catchall_to_scode(Env, X, Alts, []). -catchall_to_scode(Env, X, [{'case', {var, _, Y}, Split} | _], Acc) -> +catchall_to_scode(Env, X, [{'case', {var, Y}, Split} | _], Acc) -> Env1 = bind_var(Y, lookup_var(Env, X), Env), {split_to_scode(Env1, Split), lists:reverse(Acc)}; catchall_to_scode(Env, X, [Alt | Alts], Acc) -> -- 2.30.2 From 801231d6283512c7a0e15365abd2202f1f401935 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 19 Nov 2022 13:53:37 +0300 Subject: [PATCH 36/92] Fill out empty fann() when possible --- src/aeso_ast_to_fcode.erl | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 280ef80..c588237 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -662,22 +662,22 @@ expr_to_fcode(Env, {record_t, FieldTypes}, {record, Ann, Rec, Fields}) -> Expand = length(Fields) == length(FieldTypes), Updates = [ {I, field_value(FT, Fields)} || {I, FT} <- indexed(FieldTypes) ], Body = case Expand of - true -> {tuple, [], lists:map(Comp, Updates)}; + true -> {tuple, FAnn, lists:map(Comp, Updates)}; false -> lists:foldr(Set, {var, FAnn, X}, Updates) end, {'let', FAnn, X, expr_to_fcode(Env, Rec), Body}; %% Lists -expr_to_fcode(Env, _Type, {list, _, Es}) -> +expr_to_fcode(Env, _Type, {list, Ann, Es}) -> lists:foldr(fun(E, L) -> {op, to_fann(aeso_syntax:get_ann(E)), '::', [expr_to_fcode(Env, E), L]} end, - {nil, []}, Es); + {nil, to_fann(Ann)}, Es); expr_to_fcode(Env, _Type, {app, _, {'..', _}, [A, B]}) -> {def_u, FAnn, FromTo, _} = resolve_fun(Env, ["ListInternal", "from_to"]), {def, FAnn, FromTo, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]}; expr_to_fcode(Env, _Type, {list_comp, As, Yield, []}) -> - {op, to_fann(As), '::', [expr_to_fcode(Env, Yield), {nil, []}]}; + {op, to_fann(As), '::', [expr_to_fcode(Env, Yield), {nil, to_fann(As)}]}; expr_to_fcode(Env, _Type, {list_comp, As, Yield, [{comprehension_bind, Pat = {typed, _, _, PatType}, BindExpr}|Rest]}) -> Arg = fresh_name(), Env1 = bind_var(Env, Arg), @@ -689,7 +689,7 @@ expr_to_fcode(Env, _Type, {list_comp, As, Yield, [{comprehension_bind, Pat = {ty expr_to_fcode(Env, Type, {list_comp, As, Yield, [{comprehension_if, _, Cond}|Rest]}) -> make_if(expr_to_fcode(Env, Cond), expr_to_fcode(Env, Type, {list_comp, As, Yield, Rest}), - {nil, []} + {nil, to_fann(As)} ); expr_to_fcode(Env, Type, {list_comp, As, Yield, [LV = {letval, _, _, _}|Rest]}) -> expr_to_fcode(Env, Type, {block, As, [LV, {list_comp, As, Yield, Rest}]}); @@ -1120,9 +1120,9 @@ decision_tree_to_fcode(true) -> {lit, [], {bool, true}}; decision_tree_to_fcode({atom, B}) -> B; decision_tree_to_fcode({'if', A, Then, Else}) -> X = fresh_name(), - {'let', [], X, A, - {switch, [], {split, boolean, X, [{'case', {bool, false}, {nosplit, decision_tree_to_fcode(Else)}}, - {'case', {bool, true}, {nosplit, decision_tree_to_fcode(Then)}}]}}}. + {'let', get_fann(A), X, A, + {switch, get_fann(A), {split, boolean, X, [{'case', {bool, false}, {nosplit, decision_tree_to_fcode(Else)}}, + {'case', {bool, true}, {nosplit, decision_tree_to_fcode(Then)}}]}}}. %% -- Statements -- @@ -1172,8 +1172,8 @@ set_state({reg, R}, Val) -> set_state({tuple, Ls}, Val) -> ?make_let(X, Val, lists:foldr(fun({I, L}, Code) -> - {'let', [], "_", set_state(L, {proj, get_fann(Val), X, I - 1}), Code} - end, {tuple, [], []}, indexed(Ls))). + {'let', get_fann(Val), "_", set_state(L, {proj, get_fann(Val), X, I - 1}), Code} + end, {tuple, get_fann(Val), []}, indexed(Ls))). -spec get_state(state_layout()) -> fexpr(). get_state({reg, R}) -> @@ -1190,7 +1190,7 @@ builtin_to_fcode(Layout, get_state, []) -> builtin_to_fcode(_Layout, require, [Cond, Msg]) -> make_if(Cond, {tuple, get_fann(Cond), []}, {builtin, get_fann(Cond), abort, [Msg]}); builtin_to_fcode(_Layout, chain_event, [Event]) -> - {def, [], event, [Event]}; + {def, get_fann(Event), event, [Event]}; builtin_to_fcode(_Layout, map_delete, [Key, Map]) -> {op, get_fann(Map), map_delete, [Map, Key]}; builtin_to_fcode(_Layout, map_member, [Key, Map]) -> @@ -1322,8 +1322,9 @@ lifted_fun(FVs, Xs, Body) -> Closure :: fexpr(). make_closure(FVs, Xs, Body) -> Fun = add_lambda_fun(lifted_fun(FVs, Xs, Body)), - Tup = fun([Y]) -> Y; (Ys) -> {tuple, [], Ys} end, - {closure, get_fann(Body), Fun, Tup([{var, [], Y} || Y <- FVs])}. + FAnn = get_fann(Body), + Tup = fun([Y]) -> Y; (Ys) -> {tuple, FAnn, Ys} end, + {closure, FAnn, Fun, Tup([{var, FAnn, Y} || Y <- FVs])}. -spec lambda_lift_expr(state_layout(), fexpr()) -> Closure when Closure :: fexpr(). @@ -1337,10 +1338,10 @@ lambda_lift_expr(Layout, UExpr) when element(1, UExpr) == def_u; element(1, UExp _ -> [] end, Xs = [ lists:concat(["arg", I]) || I <- lists:seq(1, Ar) ], - Args = [{var, [], X} || X <- Xs] ++ ExtraArgs, + Args = [{var, get_fann(UExpr), X} || X <- Xs] ++ ExtraArgs, Body = case Tag of builtin_u -> builtin_to_fcode(Layout, F, Args); - def_u -> {def, [], F, Args} + def_u -> {def, get_fann(UExpr), F, Args} end, make_closure([], Xs, Body); lambda_lift_expr(Layout, {remote_u, FAnn, ArgsT, RetT, Ct, F}) -> -- 2.30.2 From 793a6829f61fc215b28f0de534ae7c3ca12dd8cf Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sun, 4 Dec 2022 12:18:46 +0300 Subject: [PATCH 37/92] Save debug locations for child contracts --- src/aeso_fcode_to_fate.erl | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index df9778b..050d8c9 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -84,7 +84,8 @@ compile(ChildContracts, FCode, SavedFreshNames, Options) -> try compile1(ChildContracts, FCode, SavedFreshNames, Options) after - put(variables_registers, undefined) + put(variables_registers, undefined), + put(instructions_locations, undefined) end. compile1(ChildContracts, FCode, SavedFreshNames, Options) -> @@ -98,12 +99,13 @@ compile1(ChildContracts, FCode, SavedFreshNames, Options) -> true -> remove_dbgloc(FateCode); false -> {FateCode, #{}} end, + add_instructions_locations(ContractName, DbglocMap), ?debug(compile, Options, "~s\n", [aeb_fate_asm:pp(FateCode1)]), FateCode2 = case proplists:get_value(include_child_contract_symbols, Options, false) of false -> FateCode1; true -> add_child_symbols(ChildContracts, FateCode1) end, - {FateCode2, get_variables_registers(), DbglocMap}. + {FateCode2, get_variables_registers(), get_instructions_locations()}. -spec block_dbgloc_map(bcode()) -> DbglocMap when DbglocMap :: #{integer() => {aeso_syntax:ann_file(), aeso_syntax:ann_line(), aeso_syntax:ann_col()}}. @@ -182,6 +184,16 @@ get_variables_registers() -> Vs -> Vs end. +get_instructions_locations() -> + case get(instructions_locations) of + undefined -> #{}; + IL -> IL + end. + +add_instructions_locations(Contract, Map) -> + Old = get_instructions_locations(), + put(instructions_locations, Old#{Contract => Map}). + add_variables_register(Env = #env{saved_fresh_names = SavedFreshNames}, Name, Register) -> Olds = get_variables_registers(), RealName = maps:get(Name, SavedFreshNames, Name), -- 2.30.2 From 141eea74fd9e273f359b0a389d254cc7df7c69f2 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 6 Dec 2022 17:31:57 +0300 Subject: [PATCH 38/92] Include DBGLOC instructions in the compiler output --- rebar.config | 2 +- rebar.lock | 2 +- src/aeso_compiler.erl | 7 ++-- src/aeso_fcode_to_fate.erl | 69 ++++---------------------------------- 4 files changed, 11 insertions(+), 69 deletions(-) diff --git a/rebar.config b/rebar.config index d22de4b..3e7f773 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {tag, "v3.2.0"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "0939e29"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 85a9709..c979d6a 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"2a0a397afad6b45da52572170f718194018bf33c"}}, + {ref,"0939e29448b5d0cdba6a4b0c56e4785ea7026087"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_compiler.erl b/src/aeso_compiler.erl index 41f7de5..c38a798 100644 --- a/src/aeso_compiler.erl +++ b/src/aeso_compiler.erl @@ -119,7 +119,7 @@ from_string1(ContractString, Options) -> , warnings := Warnings } = string_to_code(ContractString, Options), #{ child_con_env := ChildContracts } = FCodeEnv, SavedFreshNames = maps:get(saved_fresh_names, FCodeEnv, #{}), - {FateCode, VarsRegs, DbglocMap} = aeso_fcode_to_fate:compile(ChildContracts, FCode, SavedFreshNames, Options), + {FateCode, VarsRegs} = aeso_fcode_to_fate:compile(ChildContracts, FCode, SavedFreshNames, Options), pp_assembler(FateCode, Options), ByteCode = aeb_fate_code:serialize(FateCode, []), {ok, Version} = version(), @@ -132,8 +132,7 @@ from_string1(ContractString, Options) -> payable => maps:get(payable, FCode), warnings => Warnings }, - ResDbg = Res#{ variables_registers => VarsRegs, - instructions_lines => DbglocMap }, + ResDbg = Res#{ variables_registers => VarsRegs }, FinalRes = case proplists:get_value(debug_info, Options, false) of true -> ResDbg; @@ -205,7 +204,7 @@ add_extra_call(Contract0, Call, Options) -> #{fcode := OrgFcode , fcode_env := #{child_con_env := ChildContracts} , ast := Ast} = string_to_code(Contract0, Options), - {FateCode, _, _} = aeso_fcode_to_fate:compile(ChildContracts, OrgFcode, #{}, []), + {FateCode, _} = aeso_fcode_to_fate:compile(ChildContracts, OrgFcode, #{}, []), %% collect all hashes and compute the first name without hash collision to SymbolHashes = maps:keys(aeb_fate_code:symbols(FateCode)), CallName = first_none_match(?CALL_NAME, SymbolHashes, diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 050d8c9..4faad6f 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -84,8 +84,7 @@ compile(ChildContracts, FCode, SavedFreshNames, Options) -> try compile1(ChildContracts, FCode, SavedFreshNames, Options) after - put(variables_registers, undefined), - put(instructions_locations, undefined) + put(variables_registers, undefined) end. compile1(ChildContracts, FCode, SavedFreshNames, Options) -> @@ -94,58 +93,12 @@ compile1(ChildContracts, FCode, SavedFreshNames, Options) -> SFuns = functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options), SFuns1 = optimize_scode(SFuns, Options), FateCode = to_basic_blocks(SFuns1), - {FateCode1, DbglocMap} = - case proplists:get_value(debug_info, Options, false) of - true -> remove_dbgloc(FateCode); - false -> {FateCode, #{}} - end, - add_instructions_locations(ContractName, DbglocMap), - ?debug(compile, Options, "~s\n", [aeb_fate_asm:pp(FateCode1)]), + ?debug(compile, Options, "~s\n", [aeb_fate_asm:pp(FateCode)]), FateCode2 = case proplists:get_value(include_child_contract_symbols, Options, false) of - false -> FateCode1; - true -> add_child_symbols(ChildContracts, FateCode1) + false -> FateCode; + true -> add_child_symbols(ChildContracts, FateCode) end, - {FateCode2, get_variables_registers(), get_instructions_locations()}. - --spec block_dbgloc_map(bcode()) -> DbglocMap when - DbglocMap :: #{integer() => {aeso_syntax:ann_file(), aeso_syntax:ann_line(), aeso_syntax:ann_col()}}. -block_dbgloc_map(BB) -> block_dbgloc_map(BB, 0, maps:new()). - --spec block_dbgloc_map(bcode(), integer(), DbglocMap) -> DbglocMap when - DbglocMap :: #{integer() => {aeso_syntax:ann_file(), aeso_syntax:ann_line(), aeso_syntax:ann_col()}}. -block_dbgloc_map([], _, DbglocMap) -> - DbglocMap; -block_dbgloc_map([{'DBGLOC', File, Line, Col} | Rest], Index, DbglocMap) -> - block_dbgloc_map(Rest, Index, maps:put(Index, {File, Line, Col}, DbglocMap)); -block_dbgloc_map([_ | Rest], Index, DbglocMap) -> - block_dbgloc_map(Rest, Index + 1, DbglocMap). - --spec remove_dbgloc(aeb_fate_code:fcode()) -> {aeb_fate_code:fcode(), DbglocMap} when - DbglocMap :: #{integer() => {aeso_syntax:ann_file(), aeso_syntax:ann_line(), aeso_syntax:ann_col()}}. -remove_dbgloc(FateCode) -> - RemoveDbglocFromBBs = - fun(_, BB) -> - IsDbg = fun({'DBGLOC', _, _, _}) -> false; - (_) -> true - end, - lists:filter(IsDbg, BB) - end, - - RemoveDbglocFromFuns = - fun(_, Fun = {_, _, BBs}) -> - NewBBs = maps:map(RemoveDbglocFromBBs, BBs), - setelement(3, Fun, NewBBs) - end, - - DbglocMapFromBBs = - fun(_, {_, _, BBs}) -> - maps:map(fun(_, BB) -> block_dbgloc_map(BB) end, BBs) - end, - - OldFuns = aeb_fate_code:functions(FateCode), - DbglocMap = maps:map(DbglocMapFromBBs, OldFuns), - NewFuns = maps:map(RemoveDbglocFromFuns, OldFuns), - {aeb_fate_code:update_functions(FateCode, NewFuns), DbglocMap}. + {FateCode2, get_variables_registers()}. make_function_id(X) -> aeb_fate_code:symbol_identifier(make_function_name(X)). @@ -184,16 +137,6 @@ get_variables_registers() -> Vs -> Vs end. -get_instructions_locations() -> - case get(instructions_locations) of - undefined -> #{}; - IL -> IL - end. - -add_instructions_locations(Contract, Map) -> - Old = get_instructions_locations(), - put(instructions_locations, Old#{Contract => Map}). - add_variables_register(Env = #env{saved_fresh_names = SavedFreshNames}, Name, Register) -> Olds = get_variables_registers(), RealName = maps:get(Name, SavedFreshNames, Name), @@ -291,7 +234,7 @@ serialize_contract_code(Env, C) -> Options = Env#env.options, SavedFreshNames = Env#env.saved_fresh_names, FCode = maps:get(C, Env#env.child_contracts), - {FateCode, _, _} = compile1(Env#env.child_contracts, FCode, SavedFreshNames, Options), + {FateCode, _} = compile1(Env#env.child_contracts, FCode, SavedFreshNames, Options), ByteCode = aeb_fate_code:serialize(FateCode, []), {ok, Version} = aeso_compiler:version(), OriginalSourceCode = proplists:get_value(original_src, Options, ""), -- 2.30.2 From 34d363f16601b284255bf0b68ae276e6c6962e76 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 6 Dec 2022 18:20:30 +0300 Subject: [PATCH 39/92] Return an empty string instead of no_file atom --- src/aeso_fcode_to_fate.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 4faad6f..a6f5022 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -761,7 +761,10 @@ dbgloc(Env, Ann) -> case proplists:get_value(debug_info, Env#env.options, false) of false -> []; true -> - File = proplists:get_value(file, Ann), + File = case proplists:get_value(file, Ann) of + no_file -> ""; + F -> F + end, Line = proplists:get_value(line, Ann), Col = proplists:get_value(col, Ann), case {Line, Col} of -- 2.30.2 From 3ed7e36d29983ec90b7caaa077ef2bc6e137ee1d Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 6 Dec 2022 19:29:07 +0300 Subject: [PATCH 40/92] Wrap args of DBGLOC in immediate tuple --- src/aeso_fcode_to_fate.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index a6f5022..ae53e42 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -770,7 +770,7 @@ dbgloc(Env, Ann) -> case {Line, Col} of {undefined, _} -> []; {_, undefined} -> []; - {Line, Col} -> [{'DBGLOC', File, Line, Col}] + {Line, Col} -> [{'DBGLOC', {immediate, File}, {immediate, Line}, {immediate, Col}}] end end. -- 2.30.2 From 7898ab39461e929b108f47634b1315ae2dedb07f Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 7 Dec 2022 18:00:54 +0300 Subject: [PATCH 41/92] Upgrade aebytecode ref in rebar.config --- rebar.config | 2 +- rebar.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index 3e7f773..5b606e9 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "0939e29"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "da64e6c"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index c979d6a..257efe8 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"0939e29448b5d0cdba6a4b0c56e4785ea7026087"}}, + {ref,"da64e6ce5157b1231f764820e1c0d83917d34488"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", -- 2.30.2 From 9619bb607126dbd6dcef99fc9e54d7311829b481 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 23 Dec 2022 20:13:20 +0300 Subject: [PATCH 42/92] Add DBG_DEF and DBG_UNDEF --- rebar.config | 2 +- rebar.lock | 2 +- src/aeso_fcode_to_fate.erl | 35 +++++++++++++++++++++++++++++------ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/rebar.config b/rebar.config index 5b606e9..61b8900 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "da64e6c"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "dd6ec9b"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 257efe8..31addd9 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"da64e6ce5157b1231f764820e1c0d83917d34488"}}, + {ref,"dd6ec9bc9ba7017f10538fd61abd9b89d7a5d8a3"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index ae53e42..c463485 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -128,7 +128,8 @@ function_to_scode(ChildContracts, ContractName, Functions, Name, Attrs0, Args, B [ add_variables_register(Env, Arg, Register) || proplists:get_value(debug_info, Options, false), {Arg, Register} <- Env#env.vars ], - SCode = to_scode(Env, Body), + ArgsNames = [ X || {X, _} <- lists:reverse(Env#env.vars) ], + SCode = dbg_scoped_vars(Env, ArgsNames, to_scode(Env, Body)), {Attrs, {ArgTypes, ResType1}, SCode}. get_variables_registers() -> @@ -355,13 +356,13 @@ to_scode1(Env, {op, Ann, Op, Args}) -> to_scode1(Env, {'let', Ann, X, {var, _, Y}, Body}) -> Env1 = bind_var(X, lookup_var(Env, Y), Env), - [ dbgloc(Env, Ann) | to_scode(Env1, Body) ]; + [ dbgloc(Env, Ann) | dbg_scoped_var(Env1, X, to_scode(Env1, Body)) ]; to_scode1(Env, {'let', Ann, X, Expr, Body}) -> {I, Env1} = bind_local(X, Env), - [ dbgloc(Env, Ann), - to_scode(notail(Env), Expr), - aeb_fate_ops:store({var, I}, {stack, 0}), - to_scode(Env1, Body) ]; + SCode = [ to_scode(notail(Env), Expr), + aeb_fate_ops:store({var, I}, {stack, 0}), + to_scode(Env1, Body) ], + [ dbgloc(Env, Ann) | dbg_scoped_var(Env1, X, SCode) ]; to_scode1(Env = #env{ current_function = Fun, tailpos = true }, {def, Ann, Fun, Args}) -> %% Tail-call to current function, f(e0..en). Compile to @@ -774,6 +775,26 @@ dbgloc(Env, Ann) -> end end. +dbg_scoped_vars(_Env, [], SCode) -> + SCode; +dbg_scoped_vars(Env, [Var | Rest], SCode) -> + dbg_scoped_vars(Env, Rest, dbg_scoped_var(Env, Var, SCode)). + +dbg_scoped_var(Env = #env{saved_fresh_names = SavedFreshNames}, Var, SCode) -> + case proplists:get_value(debug_info, Env#env.options, false) of + false -> SCode; + true -> + Register = lookup_var(Env, Var), + case maps:get(Var, SavedFreshNames, Var) of + ["%" | _] -> SCode; + "_" -> SCode; + VarName -> + Def = [{'DBG_DEF', {immediate, VarName}, Register}], + Undef = [{'DBG_UNDEF', {immediate, VarName}, Register}], + Def ++ SCode ++ Undef + end + end. + %% -- Phase II --------------------------------------------------------------- %% Optimize @@ -910,6 +931,8 @@ attributes(I) -> switch_body -> Pure(none, []); 'RETURN' -> Impure(pc, []); {'DBGLOC', _, _, _} -> Pure(none, []); + {'DBG_DEF', _, _} -> Pure(none, []); + {'DBG_UNDEF', _, _} -> Pure(none, []); {'RETURNR', A} -> Impure(pc, A); {'CALL', A} -> Impure(?a, [A]); {'CALL_R', A, _, B, C, D} -> Impure(?a, [A, B, C, D]); -- 2.30.2 From 04aed6670ac9d2bfdc3818101acbc85564324340 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 23 Dec 2022 21:14:02 +0300 Subject: [PATCH 43/92] Do not DBG_DEF vars with % prefix --- src/aeso_fcode_to_fate.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index c463485..6cd93b7 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -786,9 +786,9 @@ dbg_scoped_var(Env = #env{saved_fresh_names = SavedFreshNames}, Var, SCode) -> true -> Register = lookup_var(Env, Var), case maps:get(Var, SavedFreshNames, Var) of - ["%" | _] -> SCode; - "_" -> SCode; - VarName -> + "%" ++ _ -> SCode; + "_" -> SCode; + VarName -> Def = [{'DBG_DEF', {immediate, VarName}, Register}], Undef = [{'DBG_UNDEF', {immediate, VarName}, Register}], Def ++ SCode ++ Undef -- 2.30.2 From 6b7bc06c3808388ede2131b23aecc5423bc2c721 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 24 Dec 2022 11:24:53 +0300 Subject: [PATCH 44/92] Do not use DBG_DEF and DBG_UNDEF on args --- src/aeso_fcode_to_fate.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 6cd93b7..bc6e948 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -128,8 +128,9 @@ function_to_scode(ChildContracts, ContractName, Functions, Name, Attrs0, Args, B [ add_variables_register(Env, Arg, Register) || proplists:get_value(debug_info, Options, false), {Arg, Register} <- Env#env.vars ], - ArgsNames = [ X || {X, _} <- lists:reverse(Env#env.vars) ], - SCode = dbg_scoped_vars(Env, ArgsNames, to_scode(Env, Body)), + %ArgsNames = [ X || {X, _} <- lists:reverse(Env#env.vars) ], + %SCode = dbg_scoped_vars(Env, ArgsNames, to_scode(Env, Body)), + SCode = to_scode(Env, Body), {Attrs, {ArgTypes, ResType1}, SCode}. get_variables_registers() -> -- 2.30.2 From c1bf0630938ed5bee38aaf3ec4b4851b410dd3df Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 24 Dec 2022 17:52:32 +0300 Subject: [PATCH 45/92] Fix dbg_undef for args --- rebar.config | 2 +- rebar.lock | 2 +- src/aeso_fcode_to_fate.erl | 40 ++++++++++++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/rebar.config b/rebar.config index 61b8900..82c9b38 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "dd6ec9b"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "3446cd3"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 31addd9..131b465 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"dd6ec9bc9ba7017f10538fd61abd9b89d7a5d8a3"}}, + {ref,"3446cd3df6d0a2592f331999fe518f3ee083d4c1"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index bc6e948..2ecde9e 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -128,9 +128,8 @@ function_to_scode(ChildContracts, ContractName, Functions, Name, Attrs0, Args, B [ add_variables_register(Env, Arg, Register) || proplists:get_value(debug_info, Options, false), {Arg, Register} <- Env#env.vars ], - %ArgsNames = [ X || {X, _} <- lists:reverse(Env#env.vars) ], - %SCode = dbg_scoped_vars(Env, ArgsNames, to_scode(Env, Body)), - SCode = to_scode(Env, Body), + ArgsNames = [ X || {X, _} <- lists:reverse(Env#env.vars) ], + SCode = dbg_scoped_vars(Env, ArgsNames, to_scode(Env, Body)), {Attrs, {ArgTypes, ResType1}, SCode}. get_variables_registers() -> @@ -772,7 +771,7 @@ dbgloc(Env, Ann) -> case {Line, Col} of {undefined, _} -> []; {_, undefined} -> []; - {Line, Col} -> [{'DBGLOC', {immediate, File}, {immediate, Line}, {immediate, Col}}] + {_, _} -> [{'DBGLOC', {immediate, File}, {immediate, Line}, {immediate, Col}}] end end. @@ -785,17 +784,42 @@ dbg_scoped_var(Env = #env{saved_fresh_names = SavedFreshNames}, Var, SCode) -> case proplists:get_value(debug_info, Env#env.options, false) of false -> SCode; true -> - Register = lookup_var(Env, Var), case maps:get(Var, SavedFreshNames, Var) of "%" ++ _ -> SCode; "_" -> SCode; VarName -> - Def = [{'DBG_DEF', {immediate, VarName}, Register}], - Undef = [{'DBG_UNDEF', {immediate, VarName}, Register}], - Def ++ SCode ++ Undef + Register = lookup_var(Env, Var), + Def = [{'DBG_DEF', {immediate, VarName}, Register}], + Undef = [{'DBG_UNDEF', {immediate, VarName}, Register}], + Def ++ dbg_undef(Undef, SCode) end end. +dbg_undef(_Undef, missing) -> + missing; +dbg_undef(Undef, loop) -> + [Undef, loop]; +dbg_undef(Undef, switch_body) -> + [switch_body, Undef]; +dbg_undef(Undef, {switch, Arg, Type, Alts, Catch}) -> + NewAlts = [ dbg_undef(Undef, Alt) || Alt <- Alts ], + NewCatch = dbg_undef(Undef, Catch), + NewSwitch = {switch, Arg, Type, NewAlts, NewCatch}, + NewSwitch; +dbg_undef(Undef, SCode) when is_list(SCode) -> + lists:droplast(SCode) ++ [dbg_undef(Undef, lists:last(SCode))]; +dbg_undef(Undef, SCode) when is_tuple(SCode); is_atom(SCode) -> + [Mnemonic | _] = + case is_tuple(SCode) of + true -> tuple_to_list(SCode); + false -> [SCode] + end, + Op = aeb_fate_opcodes:m_to_op(Mnemonic), + case aeb_fate_opcodes:end_bb(Op) of + true -> [Undef, SCode]; + false -> [SCode, Undef] + end. + %% -- Phase II --------------------------------------------------------------- %% Optimize -- 2.30.2 From 81da836b66d9bb71bdff9246f7e0a8495a4cb74f Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sun, 25 Dec 2022 10:37:48 +0300 Subject: [PATCH 46/92] Rename DBGLOC to DBG_LOC --- rebar.config | 2 +- rebar.lock | 2 +- src/aeso_fcode_to_fate.erl | 42 +++++++++++++++++++------------------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/rebar.config b/rebar.config index 82c9b38..3403558 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "3446cd3"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "dc7a7c7"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 131b465..1c5604f 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"3446cd3df6d0a2592f331999fe518f3ee083d4c1"}}, + {ref,"dc7a7c7d6f2ccac74572e3fe6f917b348849a83f"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 2ecde9e..3cab933 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -320,49 +320,49 @@ to_scode(Env, T) -> end. to_scode1(Env, {lit, Ann, L}) -> - [ dbgloc(Env, Ann), push(?i(lit_to_fate(Env, L))) ]; + [ dbg_loc(Env, Ann), push(?i(lit_to_fate(Env, L))) ]; to_scode1(Env, {nil, Ann}) -> - [ dbgloc(Env, Ann), aeb_fate_ops:nil(?a) ]; + [ dbg_loc(Env, Ann), aeb_fate_ops:nil(?a) ]; to_scode1(Env, {var, Ann, X}) -> - [ dbgloc(Env, Ann), push(lookup_var(Env, X)) ]; + [ dbg_loc(Env, Ann), push(lookup_var(Env, X)) ]; to_scode1(Env, {con, Ann, Ar, I, As}) -> N = length(As), - [ dbgloc(Env, Ann), + [ dbg_loc(Env, Ann), [to_scode(notail(Env), A) || A <- As], aeb_fate_ops:variant(?a, ?i(Ar), ?i(I), ?i(N)) ]; to_scode1(Env, {tuple, Ann, As}) -> N = length(As), - [ dbgloc(Env, Ann), + [ dbg_loc(Env, Ann), [ to_scode(notail(Env), A) || A <- As ], tuple(N) ]; to_scode1(Env, {proj, Ann, E, I}) -> - [ dbgloc(Env, Ann), + [ dbg_loc(Env, Ann), to_scode(notail(Env), E), aeb_fate_ops:element_op(?a, ?i(I), ?a) ]; to_scode1(Env, {set_proj, Ann, R, I, E}) -> - [ dbgloc(Env, Ann), + [ dbg_loc(Env, Ann), to_scode(notail(Env), E), to_scode(notail(Env), R), aeb_fate_ops:setelement(?a, ?i(I), ?a, ?a) ]; to_scode1(Env, {op, Ann, Op, Args}) -> - [ dbgloc(Env, Ann) | call_to_scode(Env, op_to_scode(Op), Args) ]; + [ dbg_loc(Env, Ann) | call_to_scode(Env, op_to_scode(Op), Args) ]; to_scode1(Env, {'let', Ann, X, {var, _, Y}, Body}) -> Env1 = bind_var(X, lookup_var(Env, Y), Env), - [ dbgloc(Env, Ann) | dbg_scoped_var(Env1, X, to_scode(Env1, Body)) ]; + [ dbg_loc(Env, Ann) | dbg_scoped_var(Env1, X, to_scode(Env1, Body)) ]; to_scode1(Env, {'let', Ann, X, Expr, Body}) -> {I, Env1} = bind_local(X, Env), SCode = [ to_scode(notail(Env), Expr), aeb_fate_ops:store({var, I}, {stack, 0}), to_scode(Env1, Body) ], - [ dbgloc(Env, Ann) | dbg_scoped_var(Env1, X, SCode) ]; + [ dbg_loc(Env, Ann) | dbg_scoped_var(Env1, X, SCode) ]; to_scode1(Env = #env{ current_function = Fun, tailpos = true }, {def, Ann, Fun, Args}) -> %% Tail-call to current function, f(e0..en). Compile to @@ -377,7 +377,7 @@ to_scode1(Env = #env{ current_function = Fun, tailpos = true }, {def, Ann, Fun, aeb_fate_ops:store({var, I}, ?a)], {[I | Is], Acc1, Env2} end, {[], [], Env}, Args), - [ dbgloc(Env, Ann), + [ dbg_loc(Env, Ann), Code, [ aeb_fate_ops:store({arg, I}, {var, J}) || {I, J} <- lists:zip(lists:seq(0, length(Vars) - 1), @@ -386,12 +386,12 @@ to_scode1(Env = #env{ current_function = Fun, tailpos = true }, {def, Ann, Fun, to_scode1(Env, {def, Ann, Fun, Args}) -> FName = make_function_id(Fun), Lbl = aeb_fate_data:make_string(FName), - [ dbgloc(Env, Ann) | call_to_scode(Env, local_call(Env, ?i(Lbl)), Args) ]; + [ dbg_loc(Env, Ann) | call_to_scode(Env, local_call(Env, ?i(Lbl)), Args) ]; to_scode1(Env, {funcall, Ann, Fun, Args}) -> - [ dbgloc(Env, Ann) | call_to_scode(Env, [to_scode(Env, Fun), local_call(Env, ?a)], Args) ]; + [ dbg_loc(Env, Ann) | call_to_scode(Env, [to_scode(Env, Fun), local_call(Env, ?a)], Args) ]; to_scode1(Env, {builtin, Ann, B, Args}) -> - [ dbgloc(Env, Ann) | builtin_to_scode(Env, B, Args) ]; + [ dbg_loc(Env, Ann) | builtin_to_scode(Env, B, Args) ]; to_scode1(Env, {remote, Ann, ArgsT, RetT, Ct, Fun, [Gas, Value, Protected | Args]}) -> Lbl = make_function_id(Fun), @@ -415,18 +415,18 @@ to_scode1(Env, {remote, Ann, ArgsT, RetT, Ct, Fun, [Gas, Value, Protected | Args Call = aeb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?a), call_to_scode(Env, Call, [Ct, Value, Gas, Protected | Args]) end, - [ dbgloc(Env, Ann) | SCode ]; + [ dbg_loc(Env, Ann) | SCode ]; to_scode1(Env, {get_state, Ann, Reg}) -> - [ dbgloc(Env, Ann), push(?s(Reg)) ]; + [ dbg_loc(Env, Ann), push(?s(Reg)) ]; to_scode1(Env, {set_state, Ann, Reg, Val}) -> - [ dbgloc(Env, Ann) | call_to_scode(Env, [{'STORE', ?s(Reg), ?a}, tuple(0)], [Val]) ]; + [ dbg_loc(Env, Ann) | call_to_scode(Env, [{'STORE', ?s(Reg), ?a}, tuple(0)], [Val]) ]; to_scode1(Env, {closure, Ann, Fun, FVs}) -> to_scode(Env, {tuple, Ann, [{lit, Ann, {string, make_function_id(Fun)}}, FVs]}); to_scode1(Env, {switch, Ann, Case}) -> - [ dbgloc(Env, Ann) | split_to_scode(Env, Case) ]. + [ dbg_loc(Env, Ann) | split_to_scode(Env, Case) ]. local_call( Env, Fun) when Env#env.tailpos -> aeb_fate_ops:call_t(Fun); local_call(_Env, Fun) -> aeb_fate_ops:call(Fun). @@ -758,7 +758,7 @@ push(A) -> {'STORE', ?a, A}. tuple(0) -> push(?i({tuple, {}})); tuple(N) -> aeb_fate_ops:tuple(?a, N). -dbgloc(Env, Ann) -> +dbg_loc(Env, Ann) -> case proplists:get_value(debug_info, Env#env.options, false) of false -> []; true -> @@ -771,7 +771,7 @@ dbgloc(Env, Ann) -> case {Line, Col} of {undefined, _} -> []; {_, undefined} -> []; - {_, _} -> [{'DBGLOC', {immediate, File}, {immediate, Line}, {immediate, Col}}] + {_, _} -> [{'DBG_LOC', {immediate, File}, {immediate, Line}, {immediate, Col}}] end end. @@ -955,7 +955,7 @@ attributes(I) -> loop -> Impure(pc, []); switch_body -> Pure(none, []); 'RETURN' -> Impure(pc, []); - {'DBGLOC', _, _, _} -> Pure(none, []); + {'DBG_LOC', _, _, _} -> Pure(none, []); {'DBG_DEF', _, _} -> Pure(none, []); {'DBG_UNDEF', _, _} -> Pure(none, []); {'RETURNR', A} -> Impure(pc, A); -- 2.30.2 From 90666d3f33c2e4a54feaf95e433ef7da3b6cef20 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sun, 25 Dec 2022 11:11:55 +0300 Subject: [PATCH 47/92] Remove column from DBG_LOC --- rebar.config | 2 +- rebar.lock | 2 +- src/aeso_fcode_to_fate.erl | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/rebar.config b/rebar.config index 3403558..ac54995 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "dc7a7c7"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "69a1c41"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 1c5604f..3c897a7 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"dc7a7c7d6f2ccac74572e3fe6f917b348849a83f"}}, + {ref,"69a1c41a4fc31c6449bf077532c22de23f2bbe83"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 3cab933..e1872e4 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -767,11 +767,9 @@ dbg_loc(Env, Ann) -> F -> F end, Line = proplists:get_value(line, Ann), - Col = proplists:get_value(col, Ann), - case {Line, Col} of - {undefined, _} -> []; - {_, undefined} -> []; - {_, _} -> [{'DBG_LOC', {immediate, File}, {immediate, Line}, {immediate, Col}}] + case Line of + undefined -> []; + _ -> [{'DBG_LOC', {immediate, File}, {immediate, Line}}] end end. @@ -955,7 +953,7 @@ attributes(I) -> loop -> Impure(pc, []); switch_body -> Pure(none, []); 'RETURN' -> Impure(pc, []); - {'DBG_LOC', _, _, _} -> Pure(none, []); + {'DBG_LOC', _, _} -> Pure(none, []); {'DBG_DEF', _, _} -> Pure(none, []); {'DBG_UNDEF', _, _} -> Pure(none, []); {'RETURNR', A} -> Impure(pc, A); -- 2.30.2 From ef10b39fa610624ab7369e313752e9f052bdceab Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sun, 25 Dec 2022 23:33:20 +0300 Subject: [PATCH 48/92] Add missing dbg_loc in to_scode1 --- src/aeso_fcode_to_fate.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index e1872e4..65b9e3d 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -423,7 +423,7 @@ to_scode1(Env, {set_state, Ann, Reg, Val}) -> [ dbg_loc(Env, Ann) | call_to_scode(Env, [{'STORE', ?s(Reg), ?a}, tuple(0)], [Val]) ]; to_scode1(Env, {closure, Ann, Fun, FVs}) -> - to_scode(Env, {tuple, Ann, [{lit, Ann, {string, make_function_id(Fun)}}, FVs]}); + [ dbg_loc(Env, Ann) | to_scode(Env, {tuple, Ann, [{lit, Ann, {string, make_function_id(Fun)}}, FVs]}) ]; to_scode1(Env, {switch, Ann, Case}) -> [ dbg_loc(Env, Ann) | split_to_scode(Env, Case) ]. -- 2.30.2 From 9dc7ed3d97c8f57199acf898fa82cd356fd1d01f Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 27 Dec 2022 11:18:34 +0300 Subject: [PATCH 49/92] Keep a single DBG_LOC instruction per line --- src/aeso_fcode_to_fate.erl | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 65b9e3d..3162618 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -1675,7 +1675,23 @@ bb(_Name, Code) -> Blocks = lists:flatmap(fun split_calls/1, Blocks1), Labels = maps:from_list([ {Ref, I} || {I, {Ref, _}} <- with_ixs(Blocks) ]), BBs = [ set_labels(Labels, B) || B <- Blocks ], - maps:from_list(BBs). + maps:from_list(dbg_loc_filter(BBs)). + +%% Filter DBG_LOC instructions to keep one instruction per line +dbg_loc_filter(BBs) -> + dbg_loc_filter(BBs, [], [], sets:new()). + +dbg_loc_filter([], _, AllBlocks, _) -> + lists:reverse(AllBlocks); +dbg_loc_filter([{I, []} | Rest], AllOps, AllBlocks, DbgLocs) -> + dbg_loc_filter(Rest, [], [{I, lists:reverse(AllOps)} | AllBlocks], DbgLocs); +dbg_loc_filter([{I, [Op = {'DBG_LOC', _, _} | Ops]} | Rest], AllOps, AllBlocks, DbgLocs) -> + case sets:is_element(Op, DbgLocs) of + true -> dbg_loc_filter([{I, Ops} | Rest], AllOps, AllBlocks, DbgLocs); + false -> dbg_loc_filter([{I, Ops} | Rest], [Op | AllOps], AllBlocks, sets:add_element(Op, DbgLocs)) + end; +dbg_loc_filter([{I, [Op | Ops]} | Rest], AllOps, AllBlocks, DbgLocs) -> + dbg_loc_filter([{I, Ops} | Rest], [Op | AllOps], AllBlocks, DbgLocs). %% -- Break up scode into basic blocks -- -- 2.30.2 From ee4c0eee34c9e1dcd427602ab67923093b6b7d0e Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 3 Jan 2023 10:12:48 +0300 Subject: [PATCH 50/92] Remove col from fann --- src/aeso_ast_to_fcode.erl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index c588237..c477b2d 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -58,7 +58,7 @@ | {contract_code, string()} %% for CREATE, by name | {typerep, ftype()}. --type fann() :: [ {file, aeso_syntax:ann_file()} | {line, aeso_syntax:ann_line()} | {col, aeso_syntax:ann_col()} ]. +-type fann() :: [ {file, aeso_syntax:ann_file()} | {line, aeso_syntax:ann_line()} ]. -type fexpr() :: {lit, fann(), flit()} | {nil, fann()} @@ -391,8 +391,7 @@ to_fcode(Env, [{namespace, _, {con, _, Con}, Decls} | Code]) -> to_fann(Ann) -> File = proplists:lookup_all(file, Ann), Line = proplists:lookup_all(line, Ann), - Col = proplists:lookup_all(col, Ann), - lists:flatten([File, Line, Col]). + lists:flatten([File, Line]). -spec get_fann(fexpr()) -> fann(). get_fann(FExpr) -> element(2, FExpr). -- 2.30.2 From 864189ee5ec412360b337fcc74575dcea922af04 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 19 Jan 2023 16:55:09 +0300 Subject: [PATCH 51/92] Add DBG_LOC op to step at function sig --- src/aeso_ast_to_fcode.erl | 13 ++++++++++--- src/aeso_fcode_to_fate.erl | 10 ++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index c477b2d..e6f42a5 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -120,7 +120,7 @@ | any | {tvar, var_name()}. --type fun_def() :: #{ attrs := [attribute()], +-type fun_def() :: #{ attrs := [attribute() | fann()], args := [{var_name(), ftype()}], return := ftype(), body := fexpr() }. @@ -408,8 +408,11 @@ decls_to_fcode(Env, Decls) -> decl_to_fcode(Env, {fun_decl, _, _, _}) -> Env; decl_to_fcode(Env, {type_def, _Ann, Name, Args, Def}) -> typedef_to_fcode(Env, Name, Args, Def); -decl_to_fcode(Env = #{ functions := Funs }, {letfun, Ann, {id, _, Name}, Args, Ret, [{guarded, _, [], Body}]}) -> - Attrs = get_attributes(Ann), +decl_to_fcode(Env = #{ functions := Funs, options := Options }, {letfun, Ann, {id, _, Name}, Args, Ret, [{guarded, _, [], Body}]}) -> + Attrs = case proplists:get_value(debug_info, Options, false) of + true -> get_attributes_debug(Ann); + false -> get_attributes(Ann) + end, FName = lookup_fun(Env, qname(Env, Name)), FArgs = args_to_fcode(Env, Args), FRet = type_to_fcode(Env, Ret), @@ -2199,6 +2202,10 @@ get_attributes(Ann) -> [payable || proplists:get_value(payable, Ann, false)] ++ [private || not proplists:get_value(entrypoint, Ann, false)]. +-spec get_attributes_debug(aeso_syntax:ann()) -> [stateful | payable | private | fann()]. +get_attributes_debug(Ann) -> + get_attributes(Ann) ++ to_fann(Ann). + %% -- Basic utilities -- -spec indexed([term()]) -> [{integer(), term()}]. diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 3162618..2229e3e 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -123,13 +123,19 @@ functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Opt function_to_scode(ChildContracts, ContractName, Functions, Name, Attrs0, Args, Body, ResType, SavedFreshNames, Options) -> {ArgTypes, ResType1} = typesig_to_scode(Args, ResType), - Attrs = Attrs0 -- [stateful], %% Only track private and payable from here. + FilterAttrs = + fun(stateful) -> false; %% Only track private and payable from here + ({file, _}) -> false; %% This is useful only for DBG_LOC op + ({line, _}) -> false; %% This is useful only for DBG_LOC op + (_) -> true + end, + Attrs = lists:filter(FilterAttrs, Attrs0), Env = init_env(ChildContracts, ContractName, Functions, Name, Args, SavedFreshNames, Options), [ add_variables_register(Env, Arg, Register) || proplists:get_value(debug_info, Options, false), {Arg, Register} <- Env#env.vars ], ArgsNames = [ X || {X, _} <- lists:reverse(Env#env.vars) ], - SCode = dbg_scoped_vars(Env, ArgsNames, to_scode(Env, Body)), + SCode = dbg_scoped_vars(Env, ArgsNames, dbg_loc(Env, Attrs0) ++ to_scode(Env, Body)), {Attrs, {ArgTypes, ResType1}, SCode}. get_variables_registers() -> -- 2.30.2 From ed3e62b40a88e4b282beb6283d494b2d0f87710c Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 19 Jan 2023 17:37:30 +0300 Subject: [PATCH 52/92] Remove the variable-register map from debug output --- CHANGELOG.md | 1 + docs/aeso_compiler.md | 2 -- src/aeso_compiler.erl | 12 +++--------- src/aeso_fcode_to_fate.erl | 40 +++++--------------------------------- 4 files changed, 9 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25b0b4c..c5cf36f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - API functions for encoding/decoding Sophia values to/from FATE. ### Changed ### Removed +- Remove the mapping from variables to FATE registers from the compilation output. ### Fixed - Warning about unused include when there is no include. diff --git a/docs/aeso_compiler.md b/docs/aeso_compiler.md index 61ee7aa..4798ad4 100644 --- a/docs/aeso_compiler.md +++ b/docs/aeso_compiler.md @@ -53,8 +53,6 @@ The **pp_** options all print to standard output the following: The option `include_child_contract_symbols` includes the symbols of child contracts functions in the generated fate code. It is turned off by default to avoid making contracts bigger on chain. -The option `debug_info` includes information related to debugging in the compiler output. Currently this option only includes the mapping from variables to registers. - #### Options to control which compiler optimizations should run: By default all optimizations are turned on, to disable an optimization, it should be diff --git a/src/aeso_compiler.erl b/src/aeso_compiler.erl index c38a798..3dc3270 100644 --- a/src/aeso_compiler.erl +++ b/src/aeso_compiler.erl @@ -119,7 +119,7 @@ from_string1(ContractString, Options) -> , warnings := Warnings } = string_to_code(ContractString, Options), #{ child_con_env := ChildContracts } = FCodeEnv, SavedFreshNames = maps:get(saved_fresh_names, FCodeEnv, #{}), - {FateCode, VarsRegs} = aeso_fcode_to_fate:compile(ChildContracts, FCode, SavedFreshNames, Options), + FateCode = aeso_fcode_to_fate:compile(ChildContracts, FCode, SavedFreshNames, Options), pp_assembler(FateCode, Options), ByteCode = aeb_fate_code:serialize(FateCode, []), {ok, Version} = version(), @@ -132,13 +132,7 @@ from_string1(ContractString, Options) -> payable => maps:get(payable, FCode), warnings => Warnings }, - ResDbg = Res#{ variables_registers => VarsRegs }, - FinalRes = - case proplists:get_value(debug_info, Options, false) of - true -> ResDbg; - false -> Res - end, - {ok, maybe_generate_aci(FinalRes, FoldedTypedAst, Options)}. + {ok, maybe_generate_aci(Res, FoldedTypedAst, Options)}. maybe_generate_aci(Result, FoldedTypedAst, Options) -> case proplists:get_value(aci, Options) of @@ -204,7 +198,7 @@ add_extra_call(Contract0, Call, Options) -> #{fcode := OrgFcode , fcode_env := #{child_con_env := ChildContracts} , ast := Ast} = string_to_code(Contract0, Options), - {FateCode, _} = aeso_fcode_to_fate:compile(ChildContracts, OrgFcode, #{}, []), + FateCode = aeso_fcode_to_fate:compile(ChildContracts, OrgFcode, #{}, []), %% collect all hashes and compute the first name without hash collision to SymbolHashes = maps:keys(aeb_fate_code:symbols(FateCode)), CallName = first_none_match(?CALL_NAME, SymbolHashes, diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 2229e3e..27696c9 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -81,24 +81,16 @@ code_error(Err) -> compile(FCode, SavedFreshNames, Options) -> compile(#{}, FCode, SavedFreshNames, Options). compile(ChildContracts, FCode, SavedFreshNames, Options) -> - try - compile1(ChildContracts, FCode, SavedFreshNames, Options) - after - put(variables_registers, undefined) - end. - -compile1(ChildContracts, FCode, SavedFreshNames, Options) -> #{ contract_name := ContractName, functions := Functions } = FCode, SFuns = functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options), SFuns1 = optimize_scode(SFuns, Options), FateCode = to_basic_blocks(SFuns1), ?debug(compile, Options, "~s\n", [aeb_fate_asm:pp(FateCode)]), - FateCode2 = case proplists:get_value(include_child_contract_symbols, Options, false) of - false -> FateCode; - true -> add_child_symbols(ChildContracts, FateCode) - end, - {FateCode2, get_variables_registers()}. + case proplists:get_value(include_child_contract_symbols, Options, false) of + false -> FateCode; + true -> add_child_symbols(ChildContracts, FateCode) + end. make_function_id(X) -> aeb_fate_code:symbol_identifier(make_function_name(X)). @@ -131,31 +123,10 @@ function_to_scode(ChildContracts, ContractName, Functions, Name, Attrs0, Args, B end, Attrs = lists:filter(FilterAttrs, Attrs0), Env = init_env(ChildContracts, ContractName, Functions, Name, Args, SavedFreshNames, Options), - [ add_variables_register(Env, Arg, Register) || - proplists:get_value(debug_info, Options, false), - {Arg, Register} <- Env#env.vars ], ArgsNames = [ X || {X, _} <- lists:reverse(Env#env.vars) ], SCode = dbg_scoped_vars(Env, ArgsNames, dbg_loc(Env, Attrs0) ++ to_scode(Env, Body)), {Attrs, {ArgTypes, ResType1}, SCode}. -get_variables_registers() -> - case get(variables_registers) of - undefined -> #{}; - Vs -> Vs - end. - -add_variables_register(Env = #env{saved_fresh_names = SavedFreshNames}, Name, Register) -> - Olds = get_variables_registers(), - RealName = maps:get(Name, SavedFreshNames, Name), - FunName = - case Env#env.current_function of - event -> "Chain.event"; - {entrypoint, BinName} -> binary_to_list(BinName); - {local_fun, QualName} -> lists:last(QualName) - end, - New = {Env#env.contract, FunName, RealName}, - put(variables_registers, Olds#{New => Register}). - -define(tvars, '$tvars'). typesig_to_scode(Args, Res) -> @@ -214,7 +185,6 @@ next_var(#env{ vars = Vars }) -> 1 + lists:max([-1 | [J || {_, {var, J}} <- Vars]]). bind_var(Name, Var, Env = #env{ vars = Vars }) -> - proplists:get_value(debug_info, Env#env.options, false) andalso add_variables_register(Env, Name, Var), Env#env{ vars = [{Name, Var} | Vars] }. bind_local(Name, Env) -> @@ -241,7 +211,7 @@ serialize_contract_code(Env, C) -> Options = Env#env.options, SavedFreshNames = Env#env.saved_fresh_names, FCode = maps:get(C, Env#env.child_contracts), - {FateCode, _} = compile1(Env#env.child_contracts, FCode, SavedFreshNames, Options), + FateCode = compile(Env#env.child_contracts, FCode, SavedFreshNames, Options), ByteCode = aeb_fate_code:serialize(FateCode, []), {ok, Version} = aeso_compiler:version(), OriginalSourceCode = proplists:get_value(original_src, Options, ""), -- 2.30.2 From 095d0f0d0a7e6635e57a68ff867194eda741d1d7 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 8 Mar 2023 12:04:19 +0300 Subject: [PATCH 53/92] Use get_value/3 to handle default --- src/aeso_fcode_to_fate.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 27696c9..8c29e2e 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -738,11 +738,11 @@ dbg_loc(Env, Ann) -> case proplists:get_value(debug_info, Env#env.options, false) of false -> []; true -> - File = case proplists:get_value(file, Ann) of + File = case proplists:get_value(file, Ann, no_file) of no_file -> ""; F -> F end, - Line = proplists:get_value(line, Ann), + Line = proplists:get_value(line, Ann, undefined), case Line of undefined -> []; _ -> [{'DBG_LOC', {immediate, File}, {immediate, Line}}] -- 2.30.2 From 3ef72e9091e869ccd9699ca3f8a5a1dca391333f Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 8 Mar 2023 12:45:51 +0300 Subject: [PATCH 54/92] Use lookup instead of lookup_all --- src/aeso_ast_to_fcode.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index e6f42a5..5a3f8d7 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -389,9 +389,9 @@ to_fcode(Env, [{namespace, _, {con, _, Con}, Decls} | Code]) -> -spec to_fann(aeso_syntax:ann()) -> fann(). to_fann(Ann) -> - File = proplists:lookup_all(file, Ann), - Line = proplists:lookup_all(line, Ann), - lists:flatten([File, Line]). + File = proplists:lookup(file, Ann), + Line = proplists:lookup(line, Ann), + [ X || X <- [File, Line], X =/= none ]. -spec get_fann(fexpr()) -> fann(). get_fann(FExpr) -> element(2, FExpr). -- 2.30.2 From a91ff6adbd83a0416d34c0425666a55733d14308 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 8 Mar 2023 13:23:10 +0300 Subject: [PATCH 55/92] List only needed attributes --- src/aeso_fcode_to_fate.erl | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 8c29e2e..9c8b908 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -115,13 +115,7 @@ functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Opt function_to_scode(ChildContracts, ContractName, Functions, Name, Attrs0, Args, Body, ResType, SavedFreshNames, Options) -> {ArgTypes, ResType1} = typesig_to_scode(Args, ResType), - FilterAttrs = - fun(stateful) -> false; %% Only track private and payable from here - ({file, _}) -> false; %% This is useful only for DBG_LOC op - ({line, _}) -> false; %% This is useful only for DBG_LOC op - (_) -> true - end, - Attrs = lists:filter(FilterAttrs, Attrs0), + Attrs = [ A || A <- Attrs0, A == private orelse A == payable ], Env = init_env(ChildContracts, ContractName, Functions, Name, Args, SavedFreshNames, Options), ArgsNames = [ X || {X, _} <- lists:reverse(Env#env.vars) ], SCode = dbg_scoped_vars(Env, ArgsNames, dbg_loc(Env, Attrs0) ++ to_scode(Env, Body)), -- 2.30.2 From ef2bec69af7ccca89d986994d9e8afff7744c082 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 9 Mar 2023 11:59:13 +0300 Subject: [PATCH 56/92] Make debug ops impure --- src/aeso_fcode_to_fate.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 9c8b908..200e2cf 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -923,9 +923,9 @@ attributes(I) -> loop -> Impure(pc, []); switch_body -> Pure(none, []); 'RETURN' -> Impure(pc, []); - {'DBG_LOC', _, _} -> Pure(none, []); - {'DBG_DEF', _, _} -> Pure(none, []); - {'DBG_UNDEF', _, _} -> Pure(none, []); + {'DBG_LOC', _, _} -> Impure(none, []); + {'DBG_DEF', _, _} -> Impure(none, []); + {'DBG_UNDEF', _, _} -> Impure(none, []); {'RETURNR', A} -> Impure(pc, A); {'CALL', A} -> Impure(?a, [A]); {'CALL_R', A, _, B, C, D} -> Impure(?a, [A, B, C, D]); -- 2.30.2 From c6fbaaaf7513cb8e2c0350b0350ed8f73e839499 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 14 Mar 2023 08:06:32 +0300 Subject: [PATCH 57/92] Split complicated code and add comment --- src/aeso_fcode_to_fate.erl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 200e2cf..b8df547 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -118,8 +118,12 @@ function_to_scode(ChildContracts, ContractName, Functions, Name, Attrs0, Args, B Attrs = [ A || A <- Attrs0, A == private orelse A == payable ], Env = init_env(ChildContracts, ContractName, Functions, Name, Args, SavedFreshNames, Options), ArgsNames = [ X || {X, _} <- lists:reverse(Env#env.vars) ], - SCode = dbg_scoped_vars(Env, ArgsNames, dbg_loc(Env, Attrs0) ++ to_scode(Env, Body)), - {Attrs, {ArgTypes, ResType1}, SCode}. + + %% DBG_LOC is added before the function body to make it possible to break + %% at the function signature + SCode = dbg_loc(Env, Attrs0) ++ to_scode(Env, Body), + ScopedSCode = dbg_scoped_vars(Env, ArgsNames, SCode), + {Attrs, {ArgTypes, ResType1}, ScopedSCode}. -define(tvars, '$tvars'). -- 2.30.2 From 7a1e94c1e6bac07162f5c33a0b85965694a9ae4a Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 14 Mar 2023 09:09:07 +0300 Subject: [PATCH 58/92] Fix annotations --- src/aeso_ast_to_fcode.erl | 112 ++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 58 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 5a3f8d7..3e79c69 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -576,9 +576,9 @@ expr_to_fcode(_Env, _Type, {oracle_query_id, Ann, K}) -> {lit, to_fann(Ann), {or expr_to_fcode(_Env, _Type, {bytes, Ann, B}) -> {lit, to_fann(Ann), {bytes, B}}; %% Variables -expr_to_fcode(Env, _Type, {id, _, X}) -> resolve_var(Env, [X]); -expr_to_fcode(Env, Type, {qid, _, X}) -> - case resolve_var(Env, X) of +expr_to_fcode(Env, _Type, {id, Ann, X}) -> resolve_var(Env, Ann, [X]); +expr_to_fcode(Env, Type, {qid, Ann, X}) -> + case resolve_var(Env, Ann, X) of {builtin_u, FAnn, B, Ar} when B =:= oracle_query; B =:= oracle_get_question; B =:= oracle_get_answer; @@ -674,8 +674,8 @@ expr_to_fcode(Env, _Type, {list, Ann, Es}) -> lists:foldr(fun(E, L) -> {op, to_fann(aeso_syntax:get_ann(E)), '::', [expr_to_fcode(Env, E), L]} end, {nil, to_fann(Ann)}, Es); -expr_to_fcode(Env, _Type, {app, _, {'..', _}, [A, B]}) -> - {def_u, FAnn, FromTo, _} = resolve_fun(Env, ["ListInternal", "from_to"]), +expr_to_fcode(Env, _Type, {app, As, {'..', _}, [A, B]}) -> + {def_u, FAnn, FromTo, _} = resolve_fun(Env, As, ["ListInternal", "from_to"]), {def, FAnn, FromTo, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]}; expr_to_fcode(Env, _Type, {list_comp, As, Yield, []}) -> @@ -686,7 +686,7 @@ expr_to_fcode(Env, _Type, {list_comp, As, Yield, [{comprehension_bind, Pat = {ty Bind = {lam, to_fann(As), [Arg], expr_to_fcode(Env1, {switch, As, {typed, As, {id, As, Arg}, PatType}, [{'case', As, Pat, [{guarded, As, [], {list_comp, As, Yield, Rest}}]}, {'case', As, {id, As, "_"}, [{guarded, As, [], {list, As, []}}]}]})}, - {def_u, FAnn, FlatMap, _} = resolve_fun(Env, ["ListInternal", "flat_map"]), + {def_u, FAnn, FlatMap, _} = resolve_fun(Env, As, ["ListInternal", "flat_map"]), {def, FAnn, FlatMap, [Bind, expr_to_fcode(Env, BindExpr)]}; expr_to_fcode(Env, Type, {list_comp, As, Yield, [{comprehension_if, _, Cond}|Rest]}) -> make_if(expr_to_fcode(Env, Cond), @@ -742,7 +742,7 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A Args1 = get_named_args(NamedArgsT, Args), FArgs = [expr_to_fcode(Env, Arg) || Arg <- Args1], case expr_to_fcode(Env, Fun) of - {builtin_u, _, B, _Ar, TypeArgs} -> builtin_to_fcode(state_layout(Env), B, FArgs ++ TypeArgs); + {builtin_u, FAnn, B, _Ar, TypeArgs} -> builtin_to_fcode(state_layout(Env), FAnn, B, FArgs ++ TypeArgs); {builtin_u, FAnn, chain_clone, _Ar} -> case ArgsT of var_args -> fcode_error({var_args_not_set, FunE}); @@ -750,17 +750,17 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A %% Here we little cheat on the typechecker, but this inconsistency %% is to be solved in `aeso_fcode_to_fate:type_to_scode/1` FInitArgsT = aeb_fate_data:make_typerep([type_to_fcode(Env, T) || T <- ArgsT]), - builtin_to_fcode(state_layout(Env), chain_clone, [{lit, FAnn, FInitArgsT}|FArgs]) + builtin_to_fcode(state_layout(Env), FAnn, chain_clone, [{lit, FAnn, FInitArgsT}|FArgs]) end; {builtin_u, FAnn, chain_create, _Ar} -> case {ArgsT, Type} of {var_args, _} -> fcode_error({var_args_not_set, FunE}); {_, {con, _, Contract}} -> FInitArgsT = aeb_fate_data:make_typerep([type_to_fcode(Env, T) || T <- ArgsT]), - builtin_to_fcode(state_layout(Env), chain_create, [{lit, FAnn, {contract_code, Contract}}, {lit, FAnn, FInitArgsT}|FArgs]); + builtin_to_fcode(state_layout(Env), FAnn, chain_create, [{lit, FAnn, {contract_code, Contract}}, {lit, FAnn, FInitArgsT}|FArgs]); {_, _} -> fcode_error({not_a_contract_type, Type}) end; - {builtin_u, _, B, _Ar} -> builtin_to_fcode(state_layout(Env), B, FArgs); + {builtin_u, FAnn, B, _Ar} -> builtin_to_fcode(state_layout(Env), FAnn, B, FArgs); {def_u, FAnn, F, _Ar} -> {def, FAnn, F, FArgs}; {remote_u, FAnn, RArgsT, RRetT, Ct, RFun} -> {remote, FAnn, RArgsT, RRetT, Ct, RFun, FArgs}; FFun -> @@ -1168,48 +1168,44 @@ op_builtins() -> mcl_bls12_381_int_to_fr, mcl_bls12_381_int_to_fp, mcl_bls12_381_fr_to_int, mcl_bls12_381_fp_to_int ]. --spec set_state(state_layout(), fexpr()) -> fexpr(). -set_state({reg, R}, Val) -> - {set_state, get_fann(Val), R, Val}; -set_state({tuple, Ls}, Val) -> +-spec set_state(state_layout(), fann(), fexpr()) -> fexpr(). +set_state({reg, R}, FAnn, Val) -> + {set_state, FAnn, R, Val}; +set_state({tuple, Ls}, FAnn, Val) -> ?make_let(X, Val, lists:foldr(fun({I, L}, Code) -> - {'let', get_fann(Val), "_", set_state(L, {proj, get_fann(Val), X, I - 1}), Code} - end, {tuple, get_fann(Val), []}, indexed(Ls))). + {'let', FAnn, "_", set_state(L, FAnn, {proj, FAnn, X, I - 1}), Code} + end, {tuple, FAnn, []}, indexed(Ls))). --spec get_state(state_layout()) -> fexpr(). -get_state({reg, R}) -> - {get_state, [], R}; -get_state({tuple, Ls}) -> - {tuple, [], [get_state(L) || L <- Ls]}. +-spec get_state(state_layout(), fann()) -> fexpr(). +get_state({reg, R}, FAnn) -> + {get_state, FAnn, R}; +get_state({tuple, Ls}, FAnn) -> + {tuple, FAnn, [get_state(L, FAnn) || L <- Ls]}. --spec builtin_to_fcode(state_layout(), BuiltinFun, [fexpr()]) -> fexpr() when +-spec builtin_to_fcode(state_layout(), fann(), BuiltinFun, [fexpr()]) -> fexpr() when BuiltinFun :: atom(). %% No need to mention all of them -builtin_to_fcode(Layout, set_state, [Val]) -> - set_state(Layout, Val); -builtin_to_fcode(Layout, get_state, []) -> - get_state(Layout); -builtin_to_fcode(_Layout, require, [Cond, Msg]) -> - make_if(Cond, {tuple, get_fann(Cond), []}, {builtin, get_fann(Cond), abort, [Msg]}); -builtin_to_fcode(_Layout, chain_event, [Event]) -> - {def, get_fann(Event), event, [Event]}; -builtin_to_fcode(_Layout, map_delete, [Key, Map]) -> - {op, get_fann(Map), map_delete, [Map, Key]}; -builtin_to_fcode(_Layout, map_member, [Key, Map]) -> - {op, get_fann(Map), map_member, [Map, Key]}; -builtin_to_fcode(_Layout, map_lookup, [Key0, Map0]) -> +builtin_to_fcode(Layout, FAnn, set_state, [Val]) -> + set_state(Layout, FAnn, Val); +builtin_to_fcode(Layout, FAnn, get_state, []) -> + get_state(Layout, FAnn); +builtin_to_fcode(_Layout, FAnn, require, [Cond, Msg]) -> + make_if(Cond, {tuple, FAnn, []}, {builtin, FAnn, abort, [Msg]}); +builtin_to_fcode(_Layout, FAnn, chain_event, [Event]) -> + {def, FAnn, event, [Event]}; +builtin_to_fcode(_Layout, FAnn, map_delete, [Key, Map]) -> + {op, FAnn, map_delete, [Map, Key]}; +builtin_to_fcode(_Layout, FAnn, map_member, [Key, Map]) -> + {op, FAnn, map_member, [Map, Key]}; +builtin_to_fcode(_Layout, FAnn, map_lookup, [Key0, Map0]) -> ?make_let(Key, Key0, ?make_let(Map, Map0, - make_if({op, get_fann(Map), map_member, [Map, Key]}, - {con, get_fann(Map), [0, 1], 1, [{op, get_fann(Map), map_get, [Map, Key]}]}, - {con, get_fann(Map), [0, 1], 0, []}))); -builtin_to_fcode(_Layout, map_lookup_default, [Key, Map, Def]) -> - {op, get_fann(Map), map_get_d, [Map, Key, Def]}; -builtin_to_fcode(_Layout, Builtin, Args) -> - FAnn = case Args of - [Arg | _] -> to_fann(aeso_syntax:get_ann(Arg)); - _ -> [] - end, + make_if({op, FAnn, map_member, [Map, Key]}, + {con, FAnn, [0, 1], 1, [{op, FAnn, map_get, [Map, Key]}]}, + {con, FAnn, [0, 1], 0, []}))); +builtin_to_fcode(_Layout, FAnn, map_lookup_default, [Key, Map, Def]) -> + {op, FAnn, map_get_d, [Map, Key, Def]}; +builtin_to_fcode(_Layout, FAnn, Builtin, Args) -> case lists:member(Builtin, op_builtins()) of true -> {op, FAnn, Builtin, Args}; false -> {builtin, FAnn, Builtin, Args} @@ -1226,7 +1222,7 @@ add_init_function(Env, Funs0) -> InitName = {entrypoint, <<"init">>}, InitFun = #{ body := InitBody} = maps:get(InitName, Funs), Funs1 = Funs#{ InitName => InitFun#{ return => {tuple, []}, - body => builtin_to_fcode(state_layout(Env), set_state, [InitBody]) } }, + body => builtin_to_fcode(state_layout(Env), [], set_state, [InitBody]) } }, Funs1 end. @@ -1342,7 +1338,7 @@ lambda_lift_expr(Layout, UExpr) when element(1, UExpr) == def_u; element(1, UExp Xs = [ lists:concat(["arg", I]) || I <- lists:seq(1, Ar) ], Args = [{var, get_fann(UExpr), X} || X <- Xs] ++ ExtraArgs, Body = case Tag of - builtin_u -> builtin_to_fcode(Layout, F, Args); + builtin_u -> builtin_to_fcode(Layout, get_fann(UExpr), F, Args); def_u -> {def, get_fann(UExpr), F, Args} end, make_closure([], Xs, Body); @@ -1843,19 +1839,19 @@ bind_vars(Env, Xs) -> -spec bind_var(env(), var_name()) -> env(). bind_var(Env = #{ vars := Vars }, X) -> Env#{ vars := [X | Vars] }. --spec resolve_var(env(), [aeso_syntax:name()]) -> fexpr(). -resolve_var(#{ vars := Vars } = Env, [X]) -> +-spec resolve_var(env(), aeso_syntax:ann(), [aeso_syntax:name()]) -> fexpr(). +resolve_var(#{ vars := Vars } = Env, Ann, [X]) -> case lists:member(X, Vars) of - true -> {var, [], X}; + true -> {var, to_fann(Ann), X}; false -> case resolve_const(Env, [X]) of - false -> resolve_fun(Env, [X]); + false -> resolve_fun(Env, Ann, [X]); Const -> Const end end; -resolve_var(Env, Q) -> +resolve_var(Env, Ann, Q) -> case resolve_const(Env, Q) of - false -> resolve_fun(Env, Q); + false -> resolve_fun(Env, Ann, Q); Const -> Const end. @@ -1865,13 +1861,13 @@ resolve_const(#{ consts := Consts }, Q) -> Val -> Val end. --spec resolve_fun(env(), [aeso_syntax:name()]) -> fexpr(). -resolve_fun(#{ fun_env := Funs, builtins := Builtin } = Env, Q) -> +-spec resolve_fun(env(), aeso_syntax:ann(), [aeso_syntax:name()]) -> fexpr(). +resolve_fun(#{ fun_env := Funs, builtins := Builtin } = Env, Ann, Q) -> case {maps:get(Q, Funs, not_found), maps:get(Q, Builtin, not_found)} of {not_found, not_found} -> internal_error({unbound_variable, Q}); - {_, {B, none}} -> builtin_to_fcode(state_layout(Env), B, []); - {_, {B, Ar}} -> {builtin_u, [], B, Ar}; - {{Fun, Ar}, _} -> {def_u, [], Fun, Ar} + {_, {B, none}} -> builtin_to_fcode(state_layout(Env), to_fann(Ann), B, []); + {_, {B, Ar}} -> {builtin_u, to_fann(Ann), B, Ar}; + {{Fun, Ar}, _} -> {def_u, to_fann(Ann), Fun, Ar} end. -spec init_fresh_names([option()]) -> term(). -- 2.30.2 From cdd3c514b5be7342c5a43b82e6556bea7e6096bc Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 14 Mar 2023 09:10:22 +0300 Subject: [PATCH 59/92] Fix indenting --- src/aeso_ast_to_fcode.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 3e79c69..d4ab1db 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -760,7 +760,7 @@ expr_to_fcode(Env, _, {app, _, Fun = {typed, Ann, FunE, {fun_t, _, NamedArgsT, A builtin_to_fcode(state_layout(Env), FAnn, chain_create, [{lit, FAnn, {contract_code, Contract}}, {lit, FAnn, FInitArgsT}|FArgs]); {_, _} -> fcode_error({not_a_contract_type, Type}) end; - {builtin_u, FAnn, B, _Ar} -> builtin_to_fcode(state_layout(Env), FAnn, B, FArgs); + {builtin_u, FAnn, B, _Ar} -> builtin_to_fcode(state_layout(Env), FAnn, B, FArgs); {def_u, FAnn, F, _Ar} -> {def, FAnn, F, FArgs}; {remote_u, FAnn, RArgsT, RRetT, Ct, RFun} -> {remote, FAnn, RArgsT, RRetT, Ct, RFun, FArgs}; FFun -> -- 2.30.2 From 7e8db136b2fcb17ce45213b123e33c424e8a1e43 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 14 Mar 2023 09:20:36 +0300 Subject: [PATCH 60/92] Remove dbg_loc before closure --- src/aeso_fcode_to_fate.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index b8df547..4b3255a 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -397,7 +397,7 @@ to_scode1(Env, {set_state, Ann, Reg, Val}) -> [ dbg_loc(Env, Ann) | call_to_scode(Env, [{'STORE', ?s(Reg), ?a}, tuple(0)], [Val]) ]; to_scode1(Env, {closure, Ann, Fun, FVs}) -> - [ dbg_loc(Env, Ann) | to_scode(Env, {tuple, Ann, [{lit, Ann, {string, make_function_id(Fun)}}, FVs]}) ]; + [ to_scode(Env, {tuple, Ann, [{lit, Ann, {string, make_function_id(Fun)}}, FVs]}) ]; to_scode1(Env, {switch, Ann, Case}) -> [ dbg_loc(Env, Ann) | split_to_scode(Env, Case) ]. -- 2.30.2 From 45b0df8affe45ae68d8065a6d7a4780bb4f24c9a Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Tue, 14 Mar 2023 11:10:49 +0300 Subject: [PATCH 61/92] Add dbg_loc in to_scode --- src/aeso_fcode_to_fate.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 4b3255a..a502c33 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -288,7 +288,9 @@ term_to_fate(_GlobEnv, _Env, _) -> to_scode(Env, T) -> try term_to_fate(Env, T) of - V -> [push(?i(V))] + V -> + FAnn = element(2, T), + [dbg_loc(Env, FAnn), push(?i(V))] catch throw:not_a_fate_value -> to_scode1(Env, T) end. -- 2.30.2 From 335d91b48a7e04b29cdcd268b61812e6ee9698dc Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 17 Mar 2023 12:06:49 +0300 Subject: [PATCH 62/92] Add DBG_CALL and DBG_RETURN --- rebar.config | 2 +- rebar.lock | 2 +- src/aeso_fcode_to_fate.erl | 55 ++++++++++++++++++++++++++++++-------- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/rebar.config b/rebar.config index ac54995..dbe87b2 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "69a1c41"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "a620c9c"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 3c897a7..813a3bf 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"69a1c41a4fc31c6449bf077532c22de23f2bbe83"}}, + {ref,"a620c9c34b1c0ace77253ec0eabe6ac0b8e77ad2"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index a502c33..768e5ba 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -96,6 +96,7 @@ make_function_id(X) -> aeb_fate_code:symbol_identifier(make_function_name(X)). make_function_name(event) -> <<"Chain.event">>; +make_function_name(lambda) -> <<"?lambda">>; make_function_name({entrypoint, Name}) -> Name; make_function_name({local_fun, Xs}) -> list_to_binary("." ++ string:join(Xs, ".")). @@ -353,18 +354,21 @@ to_scode1(Env = #env{ current_function = Fun, tailpos = true }, {def, Ann, Fun, aeb_fate_ops:store({var, I}, ?a)], {[I | Is], Acc1, Env2} end, {[], [], Env}, Args), - [ dbg_loc(Env, Ann), - Code, - [ aeb_fate_ops:store({arg, I}, {var, J}) - || {I, J} <- lists:zip(lists:seq(0, length(Vars) - 1), - lists:reverse(Vars)) ], - loop ]; + SCode = [ dbg_loc(Env, Ann), + Code, + [ aeb_fate_ops:store({arg, I}, {var, J}) + || {I, J} <- lists:zip(lists:seq(0, length(Vars) - 1), + lists:reverse(Vars)) ], + loop ], + dbg_call_return(Env, dbg_call(Fun, true), SCode); to_scode1(Env, {def, Ann, Fun, Args}) -> FName = make_function_id(Fun), Lbl = aeb_fate_data:make_string(FName), - [ dbg_loc(Env, Ann) | call_to_scode(Env, local_call(Env, ?i(Lbl)), Args) ]; + SCode = call_to_scode(Env, local_call(Env, ?i(Lbl)), Args), + [ dbg_loc(Env, Ann) | dbg_call_return(Env, dbg_call(Fun, false), SCode) ]; to_scode1(Env, {funcall, Ann, Fun, Args}) -> - [ dbg_loc(Env, Ann) | call_to_scode(Env, [to_scode(Env, Fun), local_call(Env, ?a)], Args) ]; + SCode = call_to_scode(Env, [to_scode(Env, Fun), local_call(Env, ?a)], Args), + [ dbg_loc(Env, Ann) | dbg_call_return(Env, dbg_call(lambda, false), SCode) ]; to_scode1(Env, {builtin, Ann, B, Args}) -> [ dbg_loc(Env, Ann) | builtin_to_scode(Env, B, Args) ]; @@ -391,7 +395,7 @@ to_scode1(Env, {remote, Ann, ArgsT, RetT, Ct, Fun, [Gas, Value, Protected | Args Call = aeb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?a), call_to_scode(Env, Call, [Ct, Value, Gas, Protected | Args]) end, - [ dbg_loc(Env, Ann) | SCode ]; + [ dbg_loc(Env, Ann) | dbg_call_return(Env, dbg_call_r(?a, Fun), SCode) ]; to_scode1(Env, {get_state, Ann, Reg}) -> [ dbg_loc(Env, Ann), push(?s(Reg)) ]; @@ -780,8 +784,16 @@ dbg_undef(Undef, {switch, Arg, Type, Alts, Catch}) -> NewCatch = dbg_undef(Undef, Catch), NewSwitch = {switch, Arg, Type, NewAlts, NewCatch}, NewSwitch; +dbg_undef(Undef, []) -> + [Undef]; dbg_undef(Undef, SCode) when is_list(SCode) -> - lists:droplast(SCode) ++ [dbg_undef(Undef, lists:last(SCode))]; + FlatSCode = lists:flatten(SCode), + case lists:last(FlatSCode) of + 'DBG_RETURN' -> + dbg_undef(Undef, lists:droplast(FlatSCode)) ++ ['DBG_RETURN']; + _ -> + lists:droplast(FlatSCode) ++ [dbg_undef(Undef, lists:last(FlatSCode))] + end; dbg_undef(Undef, SCode) when is_tuple(SCode); is_atom(SCode) -> [Mnemonic | _] = case is_tuple(SCode) of @@ -794,6 +806,22 @@ dbg_undef(Undef, SCode) when is_tuple(SCode); is_atom(SCode) -> false -> [SCode, Undef] end. +dbg_call_return(Env, Call, SCode) -> + case proplists:get_value(debug_info, Env#env.options, false) of + false -> SCode; + true -> + Flat = flatten(SCode), + lists:droplast(Flat) ++ [Call, lists:last(Flat), 'DBG_RETURN'] + end. + +dbg_call(Fun, IsTailCall) -> + Name = binary_to_list(make_function_name(Fun)), + [{'DBG_CALL', {immediate, Name}, {immediate, IsTailCall}}]. + +dbg_call_r(PK, Fun) -> + Name = binary_to_list(make_function_name(Fun)), + [{'DBG_CALL_R', PK, {immediate, Name}}]. + %% -- Phase II --------------------------------------------------------------- %% Optimize @@ -932,6 +960,9 @@ attributes(I) -> {'DBG_LOC', _, _} -> Impure(none, []); {'DBG_DEF', _, _} -> Impure(none, []); {'DBG_UNDEF', _, _} -> Impure(none, []); + {'DBG_CALL', _, _} -> Impure(none, []); + {'DBG_CALL_R', _, _} -> Impure(none, []); + 'DBG_RETURN' -> Impure(none, []); {'RETURNR', A} -> Impure(pc, A); {'CALL', A} -> Impure(?a, [A]); {'CALL_R', A, _, B, C, D} -> Impure(?a, [A, B, C, D]); @@ -1874,7 +1905,9 @@ split_calls(Ref, [I | Code], Acc, Blocks) when element(1, I) == 'CALL'; element(1, I) == 'CREATE'; element(1, I) == 'CLONE'; element(1, I) == 'CLONE_G'; - element(1, I) == 'jumpif' -> + element(1, I) == 'jumpif'; + element(1, I) == 'CALL_T' andalso Code =/= []; + I == loop andalso Code =/= [] -> split_calls(make_ref(), Code, [], [{Ref, lists:reverse([I | Acc])} | Blocks]); split_calls(Ref, [{'ABORT', _} = I | _Code], Acc, Blocks) -> lists:reverse([{Ref, lists:reverse([I | Acc])} | Blocks]); -- 2.30.2 From bc4f3fdbbde6547f4523a92010da824dee7ab8bc Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 17 Mar 2023 17:34:55 +0300 Subject: [PATCH 63/92] Separate the split at CALL_T and loop --- src/aeso_fcode_to_fate.erl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 768e5ba..3c349bc 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -1892,7 +1892,8 @@ tweak_returns(Code) -> Code. %% -- Split basic blocks at CALL instructions -- %% Calls can only return to a new basic block. Also splits at JUMPIF instructions. - +%% Split at CALL_T and JUMP only when DBG_RETURN op is enabled + split_calls({Ref, Code}) -> split_calls(Ref, Code, [], []). @@ -1905,9 +1906,11 @@ split_calls(Ref, [I | Code], Acc, Blocks) when element(1, I) == 'CALL'; element(1, I) == 'CREATE'; element(1, I) == 'CLONE'; element(1, I) == 'CLONE_G'; - element(1, I) == 'jumpif'; - element(1, I) == 'CALL_T' andalso Code =/= []; - I == loop andalso Code =/= [] -> + element(1, I) == 'jumpif' -> + split_calls(make_ref(), Code, [], [{Ref, lists:reverse([I | Acc])} | Blocks]); +split_calls(Ref, [I | Code = ['DBG_RETURN' | _]], Acc, Blocks) + when element(1, I) == 'CALL_T'; + I == loop -> split_calls(make_ref(), Code, [], [{Ref, lists:reverse([I | Acc])} | Blocks]); split_calls(Ref, [{'ABORT', _} = I | _Code], Acc, Blocks) -> lists:reverse([{Ref, lists:reverse([I | Acc])} | Blocks]); -- 2.30.2 From 7e3d8ea102711221fc2e0810e82e87c4ff391c32 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 17 Mar 2023 18:11:50 +0300 Subject: [PATCH 64/92] Revert "Separate the split at CALL_T and loop" This reverts commit 4ea823a7ca798c756b20cee32f928f41092c4959. --- src/aeso_fcode_to_fate.erl | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 3c349bc..768e5ba 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -1892,8 +1892,7 @@ tweak_returns(Code) -> Code. %% -- Split basic blocks at CALL instructions -- %% Calls can only return to a new basic block. Also splits at JUMPIF instructions. -%% Split at CALL_T and JUMP only when DBG_RETURN op is enabled - + split_calls({Ref, Code}) -> split_calls(Ref, Code, [], []). @@ -1906,11 +1905,9 @@ split_calls(Ref, [I | Code], Acc, Blocks) when element(1, I) == 'CALL'; element(1, I) == 'CREATE'; element(1, I) == 'CLONE'; element(1, I) == 'CLONE_G'; - element(1, I) == 'jumpif' -> - split_calls(make_ref(), Code, [], [{Ref, lists:reverse([I | Acc])} | Blocks]); -split_calls(Ref, [I | Code = ['DBG_RETURN' | _]], Acc, Blocks) - when element(1, I) == 'CALL_T'; - I == loop -> + element(1, I) == 'jumpif'; + element(1, I) == 'CALL_T' andalso Code =/= []; + I == loop andalso Code =/= [] -> split_calls(make_ref(), Code, [], [{Ref, lists:reverse([I | Acc])} | Blocks]); split_calls(Ref, [{'ABORT', _} = I | _Code], Acc, Blocks) -> lists:reverse([{Ref, lists:reverse([I | Acc])} | Blocks]); -- 2.30.2 From 61ffa8f84916f0fee0d76e97dc2a0659d42a11e5 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 17 Mar 2023 18:11:53 +0300 Subject: [PATCH 65/92] Revert "Add DBG_CALL and DBG_RETURN" This reverts commit c406c6feb09b6a5bb859c38d634f08208c901e5a. --- rebar.config | 2 +- rebar.lock | 2 +- src/aeso_fcode_to_fate.erl | 55 ++++++++------------------------------ 3 files changed, 13 insertions(+), 46 deletions(-) diff --git a/rebar.config b/rebar.config index dbe87b2..ac54995 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "a620c9c"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "69a1c41"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 813a3bf..3c897a7 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"a620c9c34b1c0ace77253ec0eabe6ac0b8e77ad2"}}, + {ref,"69a1c41a4fc31c6449bf077532c22de23f2bbe83"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 768e5ba..a502c33 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -96,7 +96,6 @@ make_function_id(X) -> aeb_fate_code:symbol_identifier(make_function_name(X)). make_function_name(event) -> <<"Chain.event">>; -make_function_name(lambda) -> <<"?lambda">>; make_function_name({entrypoint, Name}) -> Name; make_function_name({local_fun, Xs}) -> list_to_binary("." ++ string:join(Xs, ".")). @@ -354,21 +353,18 @@ to_scode1(Env = #env{ current_function = Fun, tailpos = true }, {def, Ann, Fun, aeb_fate_ops:store({var, I}, ?a)], {[I | Is], Acc1, Env2} end, {[], [], Env}, Args), - SCode = [ dbg_loc(Env, Ann), - Code, - [ aeb_fate_ops:store({arg, I}, {var, J}) - || {I, J} <- lists:zip(lists:seq(0, length(Vars) - 1), - lists:reverse(Vars)) ], - loop ], - dbg_call_return(Env, dbg_call(Fun, true), SCode); + [ dbg_loc(Env, Ann), + Code, + [ aeb_fate_ops:store({arg, I}, {var, J}) + || {I, J} <- lists:zip(lists:seq(0, length(Vars) - 1), + lists:reverse(Vars)) ], + loop ]; to_scode1(Env, {def, Ann, Fun, Args}) -> FName = make_function_id(Fun), Lbl = aeb_fate_data:make_string(FName), - SCode = call_to_scode(Env, local_call(Env, ?i(Lbl)), Args), - [ dbg_loc(Env, Ann) | dbg_call_return(Env, dbg_call(Fun, false), SCode) ]; + [ dbg_loc(Env, Ann) | call_to_scode(Env, local_call(Env, ?i(Lbl)), Args) ]; to_scode1(Env, {funcall, Ann, Fun, Args}) -> - SCode = call_to_scode(Env, [to_scode(Env, Fun), local_call(Env, ?a)], Args), - [ dbg_loc(Env, Ann) | dbg_call_return(Env, dbg_call(lambda, false), SCode) ]; + [ dbg_loc(Env, Ann) | call_to_scode(Env, [to_scode(Env, Fun), local_call(Env, ?a)], Args) ]; to_scode1(Env, {builtin, Ann, B, Args}) -> [ dbg_loc(Env, Ann) | builtin_to_scode(Env, B, Args) ]; @@ -395,7 +391,7 @@ to_scode1(Env, {remote, Ann, ArgsT, RetT, Ct, Fun, [Gas, Value, Protected | Args Call = aeb_fate_ops:call_pgr(?a, Lbl, ArgType, RetType, ?a, ?a, ?a), call_to_scode(Env, Call, [Ct, Value, Gas, Protected | Args]) end, - [ dbg_loc(Env, Ann) | dbg_call_return(Env, dbg_call_r(?a, Fun), SCode) ]; + [ dbg_loc(Env, Ann) | SCode ]; to_scode1(Env, {get_state, Ann, Reg}) -> [ dbg_loc(Env, Ann), push(?s(Reg)) ]; @@ -784,16 +780,8 @@ dbg_undef(Undef, {switch, Arg, Type, Alts, Catch}) -> NewCatch = dbg_undef(Undef, Catch), NewSwitch = {switch, Arg, Type, NewAlts, NewCatch}, NewSwitch; -dbg_undef(Undef, []) -> - [Undef]; dbg_undef(Undef, SCode) when is_list(SCode) -> - FlatSCode = lists:flatten(SCode), - case lists:last(FlatSCode) of - 'DBG_RETURN' -> - dbg_undef(Undef, lists:droplast(FlatSCode)) ++ ['DBG_RETURN']; - _ -> - lists:droplast(FlatSCode) ++ [dbg_undef(Undef, lists:last(FlatSCode))] - end; + lists:droplast(SCode) ++ [dbg_undef(Undef, lists:last(SCode))]; dbg_undef(Undef, SCode) when is_tuple(SCode); is_atom(SCode) -> [Mnemonic | _] = case is_tuple(SCode) of @@ -806,22 +794,6 @@ dbg_undef(Undef, SCode) when is_tuple(SCode); is_atom(SCode) -> false -> [SCode, Undef] end. -dbg_call_return(Env, Call, SCode) -> - case proplists:get_value(debug_info, Env#env.options, false) of - false -> SCode; - true -> - Flat = flatten(SCode), - lists:droplast(Flat) ++ [Call, lists:last(Flat), 'DBG_RETURN'] - end. - -dbg_call(Fun, IsTailCall) -> - Name = binary_to_list(make_function_name(Fun)), - [{'DBG_CALL', {immediate, Name}, {immediate, IsTailCall}}]. - -dbg_call_r(PK, Fun) -> - Name = binary_to_list(make_function_name(Fun)), - [{'DBG_CALL_R', PK, {immediate, Name}}]. - %% -- Phase II --------------------------------------------------------------- %% Optimize @@ -960,9 +932,6 @@ attributes(I) -> {'DBG_LOC', _, _} -> Impure(none, []); {'DBG_DEF', _, _} -> Impure(none, []); {'DBG_UNDEF', _, _} -> Impure(none, []); - {'DBG_CALL', _, _} -> Impure(none, []); - {'DBG_CALL_R', _, _} -> Impure(none, []); - 'DBG_RETURN' -> Impure(none, []); {'RETURNR', A} -> Impure(pc, A); {'CALL', A} -> Impure(?a, [A]); {'CALL_R', A, _, B, C, D} -> Impure(?a, [A, B, C, D]); @@ -1905,9 +1874,7 @@ split_calls(Ref, [I | Code], Acc, Blocks) when element(1, I) == 'CALL'; element(1, I) == 'CREATE'; element(1, I) == 'CLONE'; element(1, I) == 'CLONE_G'; - element(1, I) == 'jumpif'; - element(1, I) == 'CALL_T' andalso Code =/= []; - I == loop andalso Code =/= [] -> + element(1, I) == 'jumpif' -> split_calls(make_ref(), Code, [], [{Ref, lists:reverse([I | Acc])} | Blocks]); split_calls(Ref, [{'ABORT', _} = I | _Code], Acc, Blocks) -> lists:reverse([{Ref, lists:reverse([I | Acc])} | Blocks]); -- 2.30.2 From 3a40ef05fc6784312c7d5b657dd3f45dd18c80a0 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 18 Mar 2023 13:50:32 +0300 Subject: [PATCH 66/92] Disable tail call optimization for better debug call stack --- rebar.config | 2 +- rebar.lock | 2 +- src/aeso_fcode_to_fate.erl | 10 ++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/rebar.config b/rebar.config index ac54995..b613dbf 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "69a1c41"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "bf3a692"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 3c897a7..04f2420 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"69a1c41a4fc31c6449bf077532c22de23f2bbe83"}}, + {ref,"bf3a692e0dbebd8ae57becb92566c9c957b0efa6"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index a502c33..2ebd22c 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -52,7 +52,8 @@ tailpos = true, child_contracts = #{}, saved_fresh_names = #{}, - options = [] }). + options = [], + debug = false }). %% -- Debugging -------------------------------------------------------------- @@ -177,7 +178,8 @@ init_env(ChildContracts, ContractName, FunNames, Name, Args, SavedFreshNames, Op current_function = Name, options = Options, tailpos = true, - saved_fresh_names = SavedFreshNames }. + saved_fresh_names = SavedFreshNames, + debug = proplists:get_value(debug_info, Options, false) }. next_var(#env{ vars = Vars }) -> 1 + lists:max([-1 | [J || {_, {var, J}} <- Vars]]). @@ -340,7 +342,7 @@ to_scode1(Env, {'let', Ann, X, Expr, Body}) -> to_scode(Env1, Body) ], [ dbg_loc(Env, Ann) | dbg_scoped_var(Env1, X, SCode) ]; -to_scode1(Env = #env{ current_function = Fun, tailpos = true }, {def, Ann, Fun, Args}) -> +to_scode1(Env = #env{ current_function = Fun, tailpos = true, debug = false }, {def, Ann, Fun, Args}) -> %% Tail-call to current function, f(e0..en). Compile to %% [ let xi = ei ] %% [ STORE argi xi ] @@ -404,7 +406,7 @@ to_scode1(Env, {closure, Ann, Fun, FVs}) -> to_scode1(Env, {switch, Ann, Case}) -> [ dbg_loc(Env, Ann) | split_to_scode(Env, Case) ]. -local_call( Env, Fun) when Env#env.tailpos -> aeb_fate_ops:call_t(Fun); +local_call( Env = #env{debug = false}, Fun) when Env#env.tailpos -> aeb_fate_ops:call_t(Fun); local_call(_Env, Fun) -> aeb_fate_ops:call(Fun). split_to_scode(Env, {nosplit, Expr}) -> -- 2.30.2 From 49bcc483608a40c562da0b86c6917f45bf119636 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 18 Mar 2023 13:57:11 +0300 Subject: [PATCH 67/92] Rename env.debug to env.debug_info --- src/aeso_fcode_to_fate.erl | 74 +++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 2ebd22c..0c16070 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -53,7 +53,7 @@ child_contracts = #{}, saved_fresh_names = #{}, options = [], - debug = false }). + debug_info = false }). %% -- Debugging -------------------------------------------------------------- @@ -171,15 +171,15 @@ types_to_scode(Ts) -> lists:map(fun type_to_scode/1, Ts). %% -- Environment functions -- init_env(ChildContracts, ContractName, FunNames, Name, Args, SavedFreshNames, Options) -> - #env{ vars = [ {X, {arg, I}} || {I, {X, _}} <- with_ixs(Args) ], - contract = ContractName, - child_contracts = ChildContracts, - locals = FunNames, - current_function = Name, - options = Options, - tailpos = true, + #env{ vars = [ {X, {arg, I}} || {I, {X, _}} <- with_ixs(Args) ], + contract = ContractName, + child_contracts = ChildContracts, + locals = FunNames, + current_function = Name, + options = Options, + tailpos = true, saved_fresh_names = SavedFreshNames, - debug = proplists:get_value(debug_info, Options, false) }. + debug_info = proplists:get_value(debug_info, Options, false) }. next_var(#env{ vars = Vars }) -> 1 + lists:max([-1 | [J || {_, {var, J}} <- Vars]]). @@ -342,7 +342,7 @@ to_scode1(Env, {'let', Ann, X, Expr, Body}) -> to_scode(Env1, Body) ], [ dbg_loc(Env, Ann) | dbg_scoped_var(Env1, X, SCode) ]; -to_scode1(Env = #env{ current_function = Fun, tailpos = true, debug = false }, {def, Ann, Fun, Args}) -> +to_scode1(Env = #env{ current_function = Fun, tailpos = true, debug_info = false }, {def, Ann, Fun, Args}) -> %% Tail-call to current function, f(e0..en). Compile to %% [ let xi = ei ] %% [ STORE argi xi ] @@ -406,8 +406,8 @@ to_scode1(Env, {closure, Ann, Fun, FVs}) -> to_scode1(Env, {switch, Ann, Case}) -> [ dbg_loc(Env, Ann) | split_to_scode(Env, Case) ]. -local_call( Env = #env{debug = false}, Fun) when Env#env.tailpos -> aeb_fate_ops:call_t(Fun); -local_call(_Env, Fun) -> aeb_fate_ops:call(Fun). +local_call( Env = #env{debug_info = false}, Fun) when Env#env.tailpos -> aeb_fate_ops:call_t(Fun); +local_call(_Env, Fun) -> aeb_fate_ops:call(Fun). split_to_scode(Env, {nosplit, Expr}) -> [switch_body, to_scode(Env, Expr)]; @@ -736,39 +736,39 @@ push(A) -> {'STORE', ?a, A}. tuple(0) -> push(?i({tuple, {}})); tuple(N) -> aeb_fate_ops:tuple(?a, N). -dbg_loc(Env, Ann) -> - case proplists:get_value(debug_info, Env#env.options, false) of - false -> []; - true -> - File = case proplists:get_value(file, Ann, no_file) of - no_file -> ""; - F -> F - end, - Line = proplists:get_value(line, Ann, undefined), - case Line of - undefined -> []; - _ -> [{'DBG_LOC', {immediate, File}, {immediate, Line}}] - end +%% -- Debug info functions -- + +dbg_loc(#env{debug_info = false}, _) -> + []; +dbg_loc(_Env, Ann) -> + File = case proplists:get_value(file, Ann, no_file) of + no_file -> ""; + F -> F + end, + Line = proplists:get_value(line, Ann, undefined), + case Line of + undefined -> []; + _ -> [{'DBG_LOC', {immediate, File}, {immediate, Line}}] end. +dbg_scoped_vars(#env{debug_info = false}, _, SCode) -> + SCode; dbg_scoped_vars(_Env, [], SCode) -> SCode; dbg_scoped_vars(Env, [Var | Rest], SCode) -> dbg_scoped_vars(Env, Rest, dbg_scoped_var(Env, Var, SCode)). +dbg_scoped_var(#env{debug_info = false}, _, SCode) -> + SCode; dbg_scoped_var(Env = #env{saved_fresh_names = SavedFreshNames}, Var, SCode) -> - case proplists:get_value(debug_info, Env#env.options, false) of - false -> SCode; - true -> - case maps:get(Var, SavedFreshNames, Var) of - "%" ++ _ -> SCode; - "_" -> SCode; - VarName -> - Register = lookup_var(Env, Var), - Def = [{'DBG_DEF', {immediate, VarName}, Register}], - Undef = [{'DBG_UNDEF', {immediate, VarName}, Register}], - Def ++ dbg_undef(Undef, SCode) - end + case maps:get(Var, SavedFreshNames, Var) of + "%" ++ _ -> SCode; + "_" -> SCode; + VarName -> + Register = lookup_var(Env, Var), + Def = [{'DBG_DEF', {immediate, VarName}, Register}], + Undef = [{'DBG_UNDEF', {immediate, VarName}, Register}], + Def ++ dbg_undef(Undef, SCode) end. dbg_undef(_Undef, missing) -> -- 2.30.2 From 73133e39dcc31fd162c569a39355bb449a23c894 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sun, 19 Mar 2023 13:06:16 +0300 Subject: [PATCH 68/92] Upgrade aebytecode: Add DBG_CONTRACT --- rebar.config | 2 +- rebar.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index b613dbf..d4431e5 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "bf3a692"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "d85e697"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 04f2420..17dd766 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"bf3a692e0dbebd8ae57becb92566c9c957b0efa6"}}, + {ref,"d85e6976797fd0b6b0f5ecff22a9b99e3edc2feb"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", -- 2.30.2 From e579ea15e8374c34ef605c4dee6aa07902b4a84f Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sun, 19 Mar 2023 13:15:31 +0300 Subject: [PATCH 69/92] Add DBG_CONTRACT instruction --- src/aeso_fcode_to_fate.erl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 0c16070..4b78633 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -122,7 +122,7 @@ function_to_scode(ChildContracts, ContractName, Functions, Name, Attrs0, Args, B %% DBG_LOC is added before the function body to make it possible to break %% at the function signature - SCode = dbg_loc(Env, Attrs0) ++ to_scode(Env, Body), + SCode = dbg_contract(Env) ++ dbg_loc(Env, Attrs0) ++ to_scode(Env, Body), ScopedSCode = dbg_scoped_vars(Env, ArgsNames, SCode), {Attrs, {ArgTypes, ResType1}, ScopedSCode}. @@ -738,6 +738,11 @@ tuple(N) -> aeb_fate_ops:tuple(?a, N). %% -- Debug info functions -- +dbg_contract(#env{debug_info = false}) -> + []; +dbg_contract(#env{contract = Contract}) -> + [{'DBG_CONTRACT', {immediate, Contract}}]. + dbg_loc(#env{debug_info = false}, _) -> []; dbg_loc(_Env, Ann) -> @@ -934,6 +939,7 @@ attributes(I) -> {'DBG_LOC', _, _} -> Impure(none, []); {'DBG_DEF', _, _} -> Impure(none, []); {'DBG_UNDEF', _, _} -> Impure(none, []); + {'DBG_CONTRACT', _} -> Impure(none, []); {'RETURNR', A} -> Impure(pc, A); {'CALL', A} -> Impure(?a, [A]); {'CALL_R', A, _, B, C, D} -> Impure(?a, [A, B, C, D]); -- 2.30.2 From 88a1e07f13ba7045223c0f6bb0204cd9bde13d2b Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 22 Mar 2023 14:22:31 +0300 Subject: [PATCH 70/92] Check if a var name is fresh in separate function --- src/aeso_fcode_to_fate.erl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 4b78633..f26c0cb 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -766,16 +766,22 @@ dbg_scoped_vars(Env, [Var | Rest], SCode) -> dbg_scoped_var(#env{debug_info = false}, _, SCode) -> SCode; dbg_scoped_var(Env = #env{saved_fresh_names = SavedFreshNames}, Var, SCode) -> - case maps:get(Var, SavedFreshNames, Var) of - "%" ++ _ -> SCode; - "_" -> SCode; - VarName -> + VarName = maps:get(Var, SavedFreshNames, Var), + case VarName == "_" orelse is_fresh_name(VarName) of + true -> + SCode; + false -> Register = lookup_var(Env, Var), Def = [{'DBG_DEF', {immediate, VarName}, Register}], Undef = [{'DBG_UNDEF', {immediate, VarName}, Register}], Def ++ dbg_undef(Undef, SCode) end. +is_fresh_name([$% | _]) -> + true; +is_fresh_name(_) -> + false. + dbg_undef(_Undef, missing) -> missing; dbg_undef(Undef, loop) -> -- 2.30.2 From 626b27ce1a3ea1dea82651808198199dcc859248 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 29 Mar 2023 10:56:46 +0300 Subject: [PATCH 71/92] Add DBG_CONTRACT and DBG_LOC before DBG_DEF --- src/aeso_fcode_to_fate.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index f26c0cb..843ea39 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -122,9 +122,9 @@ function_to_scode(ChildContracts, ContractName, Functions, Name, Attrs0, Args, B %% DBG_LOC is added before the function body to make it possible to break %% at the function signature - SCode = dbg_contract(Env) ++ dbg_loc(Env, Attrs0) ++ to_scode(Env, Body), - ScopedSCode = dbg_scoped_vars(Env, ArgsNames, SCode), - {Attrs, {ArgTypes, ResType1}, ScopedSCode}. + SCode = to_scode(Env, Body), + DbgSCode = dbg_contract(Env) ++ dbg_loc(Env, Attrs0) ++ dbg_scoped_vars(Env, ArgsNames, SCode), + {Attrs, {ArgTypes, ResType1}, DbgSCode}. -define(tvars, '$tvars'). -- 2.30.2 From f05c2463359d0807f01de4c7a39287f8682b5ab0 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 31 Mar 2023 19:47:09 +0300 Subject: [PATCH 72/92] Save fresh names of pattern variables --- src/aeso_ast_to_fcode.erl | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index d4ab1db..9b441c7 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -1009,19 +1009,19 @@ split_alt(I, {'case', Pats, Body}) -> {SPat, {'case', Pats0 ++ InnerPats ++ Pats1, Body}}. -spec split_pat(fpat()) -> {fsplit_pat(), [fpat()]}. -split_pat(P = {var, _}) -> {{var, fresh_name()}, [P]}; +split_pat(P = {var, _}) -> {{var, fresh_name_save_fpat(P)}, [P]}; split_pat({bool, B}) -> {{bool, B}, []}; split_pat({int, N}) -> {{int, N}, []}; split_pat({string, N}) -> {{string, N}, []}; split_pat(nil) -> {nil, []}; -split_pat({'::', P, Q}) -> {{'::', fresh_name(), fresh_name()}, [P, Q]}; +split_pat({'::', P, Q}) -> {{'::', fresh_name_save_fpat(P), fresh_name_save_fpat(Q)}, [P, Q]}; split_pat({con, As, I, Pats}) -> - Xs = [fresh_name() || _ <- Pats], + Xs = [fresh_name_save_fpat(P) || P <- Pats], {{con, As, I, Xs}, Pats}; split_pat({assign, X = {var, _}, P}) -> - {{assign, fresh_name(), fresh_name()}, [X, P]}; + {{assign, fresh_name_save_fpat(X), fresh_name_save_fpat(P)}, [X, P]}; split_pat({tuple, Pats}) -> - Xs = [fresh_name() || _ <- Pats], + Xs = [fresh_name_save_fpat(P) || P <- Pats], {{tuple, Xs}, Pats}. -spec split_vars(fsplit_pat(), ftype()) -> [{var_name(), ftype()}]. @@ -1897,6 +1897,13 @@ fresh_name_save(Name) -> end, Fresh. +-spec fresh_name_save_fpat(fpat()) -> var_name(). +fresh_name_save_fpat({var, Name}) -> + fresh_name_save(Name); +fresh_name_save_fpat(FPat) -> + [fresh_name_save(Name) || Name <- pat_vars(FPat)], + fresh_name(). + -spec fresh_name() -> var_name(). fresh_name() -> fresh_name("%"). -- 2.30.2 From f41e05928b9fed13cca664caae1c7ccba991da56 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 31 Mar 2023 19:48:49 +0300 Subject: [PATCH 73/92] Implement fsplit_pat_vars for assign --- src/aeso_ast_to_fcode.erl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 9b441c7..86d6b35 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -1930,13 +1930,14 @@ pat_vars(Ps) when is_list(Ps) -> [X || P <- Ps, X <- pat_vars(P)]. -spec fsplit_pat_vars(fsplit_pat()) -> [var_name()]. fsplit_pat_vars({var, X}) -> [X || X /= "_"]; -fsplit_pat_vars({bool, _}) -> []; -fsplit_pat_vars({int, _}) -> []; -fsplit_pat_vars({string, _}) -> []; -fsplit_pat_vars(nil) -> []; -fsplit_pat_vars({'::', P, Q}) -> [P, Q]; +fsplit_pat_vars({bool, _}) -> []; +fsplit_pat_vars({int, _}) -> []; +fsplit_pat_vars({string, _}) -> []; +fsplit_pat_vars(nil) -> []; +fsplit_pat_vars({'::', P, Q}) -> [P, Q]; fsplit_pat_vars({tuple, Ps}) -> Ps; -fsplit_pat_vars({con, _, _, Ps}) -> Ps. +fsplit_pat_vars({con, _, _, Ps}) -> Ps; +fsplit_pat_vars({assign, X, P}) -> [X, P]. -spec free_vars(fexpr() | [fexpr()]) -> [var_name()]. free_vars(Xs) when is_list(Xs) -> -- 2.30.2 From b69af9a499a0688a7a95469cc1c0c9a383429143 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 5 Apr 2023 16:53:28 +0300 Subject: [PATCH 74/92] Set fann for switches --- src/aeso_ast_to_fcode.erl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 86d6b35..33528e0 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -1554,7 +1554,7 @@ simplify(Env, {proj, _, Var = {var, _, _}, I} = Expr) -> end; simplify(Env, {switch, FAnn, Split}) -> - case simpl_switch(Env, [], Split) of + case simpl_switch(Env, FAnn, [], Split) of nomatch -> {builtin, FAnn, abort, [{lit, FAnn, {string, <<"Incomplete patterns">>}}]}; Expr -> Expr end; @@ -1605,11 +1605,11 @@ nest_catchalls([C = {'case', {var, _}, {nosplit, _}} | _]) -> C; nest_catchalls([{'case', P = {var, _}, {split, Type, X, Alts}} | Catchalls]) -> {'case', P, {split, Type, X, add_catchalls(Alts, Catchalls)}}. --spec simpl_switch(expr_env(), [fcase()], fsplit()) -> fexpr() | nomatch. -simpl_switch(_Env, _, {nosplit, E}) -> E; -simpl_switch(Env, Catchalls, {split, Type, X, Alts}) -> +-spec simpl_switch(expr_env(), fann(), [fcase()], fsplit()) -> fexpr() | nomatch. +simpl_switch(_Env, _FAnn, _, {nosplit, E}) -> E; +simpl_switch(Env, FAnn, Catchalls, {split, Type, X, Alts}) -> Alts1 = add_catchalls(Alts, Catchalls), - Stuck = {switch, [], {split, Type, X, Alts1}}, + Stuck = {switch, FAnn, {split, Type, X, Alts1}}, case constructor_form(Env, {var, [], X}) of false -> Stuck; E -> simpl_case(Env, E, Alts1) @@ -1622,7 +1622,7 @@ simpl_case(Env, E, [{'case', Pat, Body} | Alts]) -> false -> simpl_case(Env, E, Alts); Binds -> Env1 = maps:merge(Env, maps:from_list(Binds)), - case simpl_switch(Env1, get_catchalls(Alts), Body) of + case simpl_switch(Env1, get_fann(E), get_catchalls(Alts), Body) of nomatch -> simpl_case(Env, E, Alts); Body1 -> let_bind(Binds, Body1) end -- 2.30.2 From f6730bd2741246f86a0d0c523181cb5c65ef7ecb Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 7 Apr 2023 14:09:30 +0300 Subject: [PATCH 75/92] Revert "Save fresh names of pattern variables" This reverts commit d2473f982996336131477df2b2115c04a55a62cb. --- src/aeso_ast_to_fcode.erl | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 33528e0..20d08b1 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -1009,19 +1009,19 @@ split_alt(I, {'case', Pats, Body}) -> {SPat, {'case', Pats0 ++ InnerPats ++ Pats1, Body}}. -spec split_pat(fpat()) -> {fsplit_pat(), [fpat()]}. -split_pat(P = {var, _}) -> {{var, fresh_name_save_fpat(P)}, [P]}; +split_pat(P = {var, _}) -> {{var, fresh_name()}, [P]}; split_pat({bool, B}) -> {{bool, B}, []}; split_pat({int, N}) -> {{int, N}, []}; split_pat({string, N}) -> {{string, N}, []}; split_pat(nil) -> {nil, []}; -split_pat({'::', P, Q}) -> {{'::', fresh_name_save_fpat(P), fresh_name_save_fpat(Q)}, [P, Q]}; +split_pat({'::', P, Q}) -> {{'::', fresh_name(), fresh_name()}, [P, Q]}; split_pat({con, As, I, Pats}) -> - Xs = [fresh_name_save_fpat(P) || P <- Pats], + Xs = [fresh_name() || _ <- Pats], {{con, As, I, Xs}, Pats}; split_pat({assign, X = {var, _}, P}) -> - {{assign, fresh_name_save_fpat(X), fresh_name_save_fpat(P)}, [X, P]}; + {{assign, fresh_name(), fresh_name()}, [X, P]}; split_pat({tuple, Pats}) -> - Xs = [fresh_name_save_fpat(P) || P <- Pats], + Xs = [fresh_name() || _ <- Pats], {{tuple, Xs}, Pats}. -spec split_vars(fsplit_pat(), ftype()) -> [{var_name(), ftype()}]. @@ -1897,13 +1897,6 @@ fresh_name_save(Name) -> end, Fresh. --spec fresh_name_save_fpat(fpat()) -> var_name(). -fresh_name_save_fpat({var, Name}) -> - fresh_name_save(Name); -fresh_name_save_fpat(FPat) -> - [fresh_name_save(Name) || Name <- pat_vars(FPat)], - fresh_name(). - -spec fresh_name() -> var_name(). fresh_name() -> fresh_name("%"). -- 2.30.2 From ccc6d98fe9ea5d43a8e3429f386a1265c5fb9a7b Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 8 Apr 2023 12:02:08 +0300 Subject: [PATCH 76/92] Add DBG_DEF for switch pattern vars --- src/aeso_ast_to_fcode.erl | 34 +++++++++++++++++----------------- src/aeso_fcode_to_fate.erl | 26 +++++++++++++------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 20d08b1..b80e481 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -87,7 +87,7 @@ | {lam, fann(), [var_name()], fexpr()}. -type fsplit() :: {split, ftype(), var_name(), [fcase()]} - | {nosplit, fexpr()}. + | {nosplit, [rename()], fexpr()}. %% Renames are needed to add DBG_DEF for switch pattern vars -type fcase() :: {'case', fsplit_pat(), fsplit()}. @@ -821,8 +821,8 @@ expr_to_fcode(_Env, Type, Expr) -> -spec make_if(fexpr(), fexpr(), fexpr()) -> fexpr(). make_if({var, FAnn, X}, Then, Else) -> {switch, FAnn, {split, boolean, X, - [{'case', {bool, false}, {nosplit, Else}}, - {'case', {bool, true}, {nosplit, Then}}]}}; + [{'case', {bool, false}, {nosplit, [], Else}}, + {'case', {bool, true}, {nosplit, [], Then}}]}}; make_if(Cond, Then, Else) -> X = fresh_name(), FAnn = get_fann(Cond), @@ -831,7 +831,7 @@ make_if(Cond, Then, Else) -> -spec make_if_no_else(fexpr(), fexpr()) -> fexpr(). make_if_no_else({var, FAnn, X}, Then) -> {switch, FAnn, {split, boolean, X, - [{'case', {bool, true}, {nosplit, Then}}]}}; + [{'case', {bool, true}, {nosplit, [], Then}}]}}; make_if_no_else(Cond, Then) -> X = fresh_name(), FAnn = get_fann(Cond), @@ -927,7 +927,7 @@ split_tree(Env, Vars, Alts = [{'case', Pats, Body} | _]) -> Ys = [ Y || {var, Y} <- Pats ], Ren = [ {Y, X} || {Y, X} <- lists:zip(Ys, Xs), X /= Y, Y /= "_" ], %% TODO: Unreachable clauses error - {nosplit, rename(Ren, Body)}; + {nosplit, Ren, rename(Ren, Body)}; I when is_integer(I) -> {Vars0, [{X, Type} | Vars1]} = lists:split(I - 1, Vars), Type1 = strip_singleton_tuples(Type), @@ -1123,8 +1123,8 @@ decision_tree_to_fcode({atom, B}) -> B; decision_tree_to_fcode({'if', A, Then, Else}) -> X = fresh_name(), {'let', get_fann(A), X, A, - {switch, get_fann(A), {split, boolean, X, [{'case', {bool, false}, {nosplit, decision_tree_to_fcode(Else)}}, - {'case', {bool, true}, {nosplit, decision_tree_to_fcode(Then)}}]}}}. + {switch, get_fann(A), {split, boolean, X, [{'case', {bool, false}, {nosplit, [], decision_tree_to_fcode(Else)}}, + {'case', {bool, true}, {nosplit, [], decision_tree_to_fcode(Then)}}]}}}. %% -- Statements -- @@ -1262,7 +1262,7 @@ event_function(_Env = #{event_type := {variant_t, EventCons}}, EventType = {vari end, Indices = [ {var, [], V} || {indexed, V} <- IVars ], Body = {builtin, [], chain_event, [Payload, Hash | Indices]}, - {'case', {con, [], Arities, Tag, Vars}, {nosplit, Body}} + {'case', {con, [], Arities, Tag, Vars}, {nosplit, [], Body}} end, #{ attrs => [private], args => [{"e", EventType}], @@ -1369,7 +1369,7 @@ lambda_lift_expr(Layout, Expr) -> {get_state, _, _} -> Expr; {switch, FAnn, S} -> {switch, FAnn, lambda_lift_expr(Layout, S)}; {split, Type, X, Alts} -> {split, Type, X, lambda_lift_exprs(Layout, Alts)}; - {nosplit, A} -> {nosplit, lambda_lift_expr(Layout, A)}; + {nosplit, Rens, A} -> {nosplit, Rens, lambda_lift_expr(Layout, A)}; {'case', P, S} -> {'case', P, lambda_lift_expr(Layout, S)} end. @@ -1601,12 +1601,12 @@ add_catchalls(Alts, Catchalls) -> end. -spec nest_catchalls([fcase()]) -> fcase(). -nest_catchalls([C = {'case', {var, _}, {nosplit, _}} | _]) -> C; +nest_catchalls([C = {'case', {var, _}, {nosplit, _, _}} | _]) -> C; nest_catchalls([{'case', P = {var, _}, {split, Type, X, Alts}} | Catchalls]) -> {'case', P, {split, Type, X, add_catchalls(Alts, Catchalls)}}. -spec simpl_switch(expr_env(), fann(), [fcase()], fsplit()) -> fexpr() | nomatch. -simpl_switch(_Env, _FAnn, _, {nosplit, E}) -> E; +simpl_switch(_Env, _FAnn, _, {nosplit, _, E}) -> E; simpl_switch(Env, FAnn, Catchalls, {split, Type, X, Alts}) -> Alts1 = add_catchalls(Alts, Catchalls), Stuck = {switch, FAnn, {split, Type, X, Alts1}}, @@ -1708,7 +1708,7 @@ read_only({remote, _, _, _, _, _, _}) -> false; read_only({builtin, _, _, _}) -> false; %% TODO: some builtins are read_only({switch, _, Split}) -> read_only(Split); read_only({split, _, _, Cases}) -> read_only(Cases); -read_only({nosplit, E}) -> read_only(E); +read_only({nosplit, _, E}) -> read_only(E); read_only({'case', _, Split}) -> read_only(Split); read_only({'let', _, _, A, B}) -> read_only([A, B]); read_only({funcall, _, _, _}) -> false; @@ -1960,7 +1960,7 @@ free_vars(Expr) -> {closure, _, _, A} -> free_vars(A); {switch, _, A} -> free_vars(A); {split, _, X, As} -> free_vars([{var, [], X} | As]); - {nosplit, A} -> free_vars(A); + {nosplit, _, A} -> free_vars(A); {'case', P, A} -> free_vars(A) -- lists:sort(fsplit_pat_vars(P)) end. @@ -1992,7 +1992,7 @@ used_defs(Expr) -> {closure, _, F, A} -> lists:umerge([F], used_defs(A)); {switch, _, A} -> used_defs(A); {split, _, _, As} -> used_defs(As); - {nosplit, A} -> used_defs(A); + {nosplit, _, A} -> used_defs(A); {'case', _, A} -> used_defs(A) end. @@ -2040,7 +2040,7 @@ bottom_up(F, Env, Expr) -> {'let', FAnn, X, E1, bottom_up(F, Env1, Body)} end; {split, Type, X, Cases} -> {split, Type, X, [bottom_up(F, Env, Case) || Case <- Cases]}; - {nosplit, E} -> {nosplit, bottom_up(F, Env, E)}; + {nosplit, Rens, E} -> {nosplit, Rens, bottom_up(F, Env, E)}; {'case', Pat, Split} -> {'case', Pat, bottom_up(F, Env, Split)} end). @@ -2164,7 +2164,7 @@ rename_spat(Ren, {assign, X, P}) -> -spec rename_split(rename(), fsplit()) -> fsplit(). rename_split(Ren, {split, Type, X, Cases}) -> {split, Type, rename_var(Ren, X), [rename_case(Ren, C) || C <- Cases]}; -rename_split(Ren, {nosplit, E}) -> {nosplit, rename(Ren, E)}. +rename_split(Ren, {nosplit, Rens, E}) -> {nosplit, Rens, rename(Ren, E)}. -spec rename_case(rename(), fcase()) -> fcase(). rename_case(Ren, {'case', Pat, Split}) -> @@ -2406,7 +2406,7 @@ pp_ftype({variant, Cons}) -> end || {I, Args} <- indexed(Cons)])). -spec pp_split(fsplit()) -> prettypr:document(). -pp_split({nosplit, E}) -> pp_fexpr(E); +pp_split({nosplit, _, E}) -> pp_fexpr(E); pp_split({split, Type, X, Alts}) -> pp_above([pp_beside([pp_text("switch("), pp_text(X), pp_text(" : "), pp_ftype(Type), pp_text(")")])] ++ [prettypr:nest(2, pp_case(Alt)) || Alt <- Alts]). diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 843ea39..0767446 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -334,13 +334,13 @@ to_scode1(Env, {op, Ann, Op, Args}) -> to_scode1(Env, {'let', Ann, X, {var, _, Y}, Body}) -> Env1 = bind_var(X, lookup_var(Env, Y), Env), - [ dbg_loc(Env, Ann) | dbg_scoped_var(Env1, X, to_scode(Env1, Body)) ]; + [ dbg_loc(Env, Ann) | dbg_scoped_vars(Env1, [X], to_scode(Env1, Body)) ]; to_scode1(Env, {'let', Ann, X, Expr, Body}) -> {I, Env1} = bind_local(X, Env), SCode = [ to_scode(notail(Env), Expr), aeb_fate_ops:store({var, I}, {stack, 0}), to_scode(Env1, Body) ], - [ dbg_loc(Env, Ann) | dbg_scoped_var(Env1, X, SCode) ]; + [ dbg_loc(Env, Ann) | dbg_scoped_vars(Env1, [X], SCode) ]; to_scode1(Env = #env{ current_function = Fun, tailpos = true, debug_info = false }, {def, Ann, Fun, Args}) -> %% Tail-call to current function, f(e0..en). Compile to @@ -409,8 +409,8 @@ to_scode1(Env, {switch, Ann, Case}) -> local_call( Env = #env{debug_info = false}, Fun) when Env#env.tailpos -> aeb_fate_ops:call_t(Fun); local_call(_Env, Fun) -> aeb_fate_ops:call(Fun). -split_to_scode(Env, {nosplit, Expr}) -> - [switch_body, to_scode(Env, Expr)]; +split_to_scode(Env, {nosplit, Renames, Expr}) -> + [switch_body, dbg_scoped_vars(Env, Renames, to_scode(Env, Expr))]; split_to_scode(Env, {split, {tuple, _}, X, Alts}) -> {Def, Alts1} = catchall_to_scode(Env, X, Alts), Arg = lookup_var(Env, X), @@ -760,20 +760,20 @@ dbg_scoped_vars(#env{debug_info = false}, _, SCode) -> SCode; dbg_scoped_vars(_Env, [], SCode) -> SCode; -dbg_scoped_vars(Env, [Var | Rest], SCode) -> - dbg_scoped_vars(Env, Rest, dbg_scoped_var(Env, Var, SCode)). +dbg_scoped_vars(Env, [{SavedVarName, Var} | Rest], SCode) -> + dbg_scoped_vars(Env, Rest, dbg_scoped_var(Env, SavedVarName, Var, SCode)); +dbg_scoped_vars(Env = #env{saved_fresh_names = SavedFreshNames}, [Var | Rest], SCode) -> + SavedVarName = maps:get(Var, SavedFreshNames, Var), + dbg_scoped_vars(Env, Rest, dbg_scoped_var(Env, SavedVarName, Var, SCode)). -dbg_scoped_var(#env{debug_info = false}, _, SCode) -> - SCode; -dbg_scoped_var(Env = #env{saved_fresh_names = SavedFreshNames}, Var, SCode) -> - VarName = maps:get(Var, SavedFreshNames, Var), - case VarName == "_" orelse is_fresh_name(VarName) of +dbg_scoped_var(Env, SavedVarName, Var, SCode) -> + case SavedVarName == "_" orelse is_fresh_name(SavedVarName) of true -> SCode; false -> Register = lookup_var(Env, Var), - Def = [{'DBG_DEF', {immediate, VarName}, Register}], - Undef = [{'DBG_UNDEF', {immediate, VarName}, Register}], + Def = [{'DBG_DEF', {immediate, SavedVarName}, Register}], + Undef = [{'DBG_UNDEF', {immediate, SavedVarName}, Register}], Def ++ dbg_undef(Undef, SCode) end. -- 2.30.2 From 39ccb44c864747c291ee255e31eac40f97ef1443 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sat, 8 Apr 2023 13:20:43 +0300 Subject: [PATCH 77/92] Fix the inability to pattern match constructors --- src/aeso_fcode_to_fate.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 0767446..97fb6b6 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -460,7 +460,7 @@ split_to_scode(Env, {split, {variant, Cons}, X, Alts}) -> {Def, Alts1} = catchall_to_scode(Env, X, Alts), Arg = lookup_var(Env, X), GetAlt = fun(I) -> - case [{Xs, S} || {'case', {con, _, _, J, Xs}, S} <- Alts1, I == J] of + case [{Xs, S} || {'case', {con, _, J, Xs}, S} <- Alts1, I == J] of [] -> missing; [{Xs, S} | _] -> {Code, Env1} = match_variant(Env, Arg, Xs), -- 2.30.2 From 55ea2caa5434ce5acb0a7b88f1234a41d61b7ce7 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Mon, 17 Apr 2023 10:55:05 +0300 Subject: [PATCH 78/92] Upgrade aebytecode dep --- rebar.config | 2 +- rebar.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rebar.config b/rebar.config index d4431e5..e3ee5a1 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "d85e697"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "3d75a9a"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 17dd766..73a9ff5 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,11 +1,11 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"d85e6976797fd0b6b0f5ecff22a9b99e3edc2feb"}}, + {ref,"3d75a9a9dc149e4e3152d273b1e1f8f6afb9eee3"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", - {ref,"eb68fe331bd476910394966b7f5ede7a74d37e35"}}, + {ref,"177bf604b2a05e940f92cf00e96e6e269e708245"}}, 1}, {<<"base58">>, {git,"https://github.com/aeternity/erl-base58.git", -- 2.30.2 From e0dd64cd228f31a48ea682a6175ed384b6134b28 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Mon, 17 Apr 2023 17:49:05 +0300 Subject: [PATCH 79/92] Upgrade aebytecode dep --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index e3ee5a1..dcc0ea5 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "3d75a9a"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "e50b4eb"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} -- 2.30.2 From f3398b9b8b4aa0357451d712825a91f8e04c5c35 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Mon, 17 Apr 2023 17:50:16 +0300 Subject: [PATCH 80/92] Update the lock file --- rebar.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.lock b/rebar.lock index 73a9ff5..1aaf5bf 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"3d75a9a9dc149e4e3152d273b1e1f8f6afb9eee3"}}, + {ref,"e50b4ebc796340d5ab502c4ec38d0a932f7750f9"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", -- 2.30.2 From 066ff0bc968c1c281f5c7c8188a8a1fd2d444fc2 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 19 May 2023 11:02:36 +0300 Subject: [PATCH 81/92] Add annotations to fexpr var --- src/aeso_ast_to_fcode.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index b80e481..8061644 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -2417,7 +2417,7 @@ pp_case({'case', Pat, Split}) -> prettypr:nest(2, pp_split(Split))]). -spec pp_pat(fsplit_pat()) -> prettypr:document(). -pp_pat({tuple, Xs}) -> pp_fexpr({tuple, [], [{var, X} || X <- Xs]}); +pp_pat({tuple, Xs}) -> pp_fexpr({tuple, [], [{var, [], X} || X <- Xs]}); pp_pat({'::', X, Xs}) -> pp_fexpr({op, [], '::', [{var, [], X}, {var, [], Xs}]}); pp_pat({con, As, I, Xs}) -> pp_fexpr({con, [], As, I, [{var, [], X} || X <- Xs]}); pp_pat({var, X}) -> pp_fexpr({var, [], X}); -- 2.30.2 From 7c6756158512e85ce5f82d1184be58e0479f3b8b Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 19 May 2023 18:46:04 +0300 Subject: [PATCH 82/92] Fix issues with pretty-printing of fexprs --- src/aeso_ast_to_fcode.erl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 8061644..997ba02 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -2301,6 +2301,8 @@ pp_par(Xs) -> prettypr:par(Xs). -spec pp_fexpr(fexpr()) -> prettypr:document(). pp_fexpr({lit, _, {typerep, T}}) -> pp_ftype(T); +pp_fexpr({lit, _, {contract_code, Contract}}) -> + pp_beside(pp_text("contract "), pp_text(Contract)); pp_fexpr({lit, _, {Tag, Lit}}) -> aeso_pretty:expr({Tag, [], Lit}); pp_fexpr({nil, _}) -> @@ -2371,9 +2373,7 @@ pp_fexpr({set_state, FAnn, R, A}) -> pp_call(pp_text("set_state"), [{lit, FAnn, {int, R}}, A]); pp_fexpr({get_state, FAnn, R}) -> pp_call(pp_text("get_state"), [{lit, FAnn, {int, R}}]); -pp_fexpr({switch, _, Split}) -> pp_split(Split); -pp_fexpr({contract_code, Contract}) -> - pp_beside(pp_text("contract "), pp_text(Contract)). +pp_fexpr({switch, _, Split}) -> pp_split(Split). -spec pp_call(prettypr:document(), [fexpr()]) -> prettypr:document(). pp_call(Fun, Args) -> @@ -2403,7 +2403,11 @@ pp_ftype({variant, Cons}) -> [ case Args of [] -> pp_fexpr({con, [], [], I - 1, []}); _ -> pp_beside(pp_fexpr({con, [], [], I - 1, []}), pp_ftype({tuple, Args})) - end || {I, Args} <- indexed(Cons)])). + end || {I, Args} <- indexed(Cons)])); +pp_ftype([]) -> + %% NOTE: This could happen with `{typerep, []}` since `[]` is not a ftype(). + %% TODO: It would be better to make sure that `{typerep, []}` does not arrive here. + pp_text("[]"). -spec pp_split(fsplit()) -> prettypr:document(). pp_split({nosplit, _, E}) -> pp_fexpr(E); -- 2.30.2 From 9208a5974e8ccda004f01fd915a84b9fc5507d22 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 25 May 2023 15:22:13 +0300 Subject: [PATCH 83/92] Use FAnn instead of get_fann(Body) --- src/aeso_ast_to_fcode.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 997ba02..b5f2694 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -1309,7 +1309,7 @@ lifted_fun([Z], Xs, Body) -> lifted_fun(FVs, Xs, Body) -> Z = "%env", FAnn = get_fann(Body), - Proj = fun({I, Y}, E) -> {'let', get_fann(Body), Y, {proj, FAnn, {var, FAnn, Z}, I - 1}, E} end, + Proj = fun({I, Y}, E) -> {'let', FAnn, Y, {proj, FAnn, {var, FAnn, Z}, I - 1}, E} end, #{ attrs => [private], args => [{Z, any} | [{X, any} || X <- Xs]], return => any, -- 2.30.2 From de52ca362a2a95660113c9db5cb867e7746b7a49 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 26 May 2023 13:53:51 +0300 Subject: [PATCH 84/92] Upgrade aebytecode version --- rebar.config | 2 +- rebar.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index dcc0ea5..474ffed 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "e50b4eb"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "0f7529b"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 1aaf5bf..46888c2 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"e50b4ebc796340d5ab502c4ec38d0a932f7750f9"}}, + {ref,"0f7529b26a28c619326f6e2dcf10b26c85b2fff2"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", -- 2.30.2 From 4c29750c3cc9c096b1d56736cfc99a0ab3c007d0 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 26 May 2023 13:54:03 +0300 Subject: [PATCH 85/92] Fix pp_fpat --- src/aeso_ast_to_fcode.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index b5f2694..8cb7c84 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -2427,7 +2427,8 @@ pp_pat({con, As, I, Xs}) -> pp_fexpr({con, [], As, I, [{var, [], X} || X < pp_pat({var, X}) -> pp_fexpr({var, [], X}); pp_pat(P = {Tag, _}) when Tag == bool; Tag == int; Tag == string -> pp_fexpr({lit, [], P}); -pp_pat(Pat) -> pp_fexpr(Pat). +pp_pat(nil) -> pp_fexpr({nil, []}); +pp_pat({assign, X, Y}) -> pp_beside([pp_text(X), pp_text(" = "), pp_text(Y)]). -spec is_infix(op()) -> boolean(). is_infix(Op) -> -- 2.30.2 From 9b9853cbfde4f6f33d636966e2c58577bbb7903f Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 26 May 2023 16:16:20 +0300 Subject: [PATCH 86/92] Fix pattern matching on fpat --- src/aeso_fcode_to_fate.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 97fb6b6..5c99d70 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -414,7 +414,7 @@ split_to_scode(Env, {nosplit, Renames, Expr}) -> split_to_scode(Env, {split, {tuple, _}, X, Alts}) -> {Def, Alts1} = catchall_to_scode(Env, X, Alts), Arg = lookup_var(Env, X), - Alt = case [ {Xs, Split} || {'case', {tuple, _, Xs}, Split} <- Alts1 ] of + Alt = case [ {Xs, Split} || {'case', {tuple, Xs}, Split} <- Alts1 ] of [] -> missing; [{Xs, S} | _] -> {Code, Env1} = match_tuple(Env, Arg, Xs), -- 2.30.2 From 271870b2a48b53d6d3ca7d5e7b8cd30297bb34d3 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 26 May 2023 16:50:35 +0300 Subject: [PATCH 87/92] Update rename when a new rename comes up --- src/aeso_ast_to_fcode.erl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 8cb7c84..6890926 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -2164,13 +2164,18 @@ rename_spat(Ren, {assign, X, P}) -> -spec rename_split(rename(), fsplit()) -> fsplit(). rename_split(Ren, {split, Type, X, Cases}) -> {split, Type, rename_var(Ren, X), [rename_case(Ren, C) || C <- Cases]}; -rename_split(Ren, {nosplit, Rens, E}) -> {nosplit, Rens, rename(Ren, E)}. +rename_split(Ren, {nosplit, Rens, E}) -> + {nosplit, update_rename(Rens, Ren), rename(Ren, E)}. -spec rename_case(rename(), fcase()) -> fcase(). rename_case(Ren, {'case', Pat, Split}) -> {Pat1, Ren1} = rename_spat(Ren, Pat), {'case', Pat1, rename_split(Ren1, Split)}. +-spec update_rename(rename(), rename()) -> rename(). +update_rename(OldRen, NewRen) -> + [{Name, proplists:get_value(Rename, NewRen, Rename)} || {Name, Rename} <- OldRen]. + %% -- Records -- -spec field_index(aeso_syntax:typedef(), aeso_syntax:name()) -> integer(). -- 2.30.2 From 3a13840451649cba55d6b0a8f0b24e1e361a4da9 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Sun, 28 May 2023 13:43:53 +0300 Subject: [PATCH 88/92] Upgrade aebytecode --- rebar.config | 2 +- rebar.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index 474ffed..202040b 100644 --- a/rebar.config +++ b/rebar.config @@ -2,7 +2,7 @@ {erl_opts, [debug_info]}. -{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {ref, "0f7529b"}}} +{deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {tag, "v3.3.0"}}} , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} diff --git a/rebar.lock b/rebar.lock index 46888c2..7d1705e 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,7 +1,7 @@ {"1.2.0", [{<<"aebytecode">>, {git,"https://github.com/aeternity/aebytecode.git", - {ref,"0f7529b26a28c619326f6e2dcf10b26c85b2fff2"}}, + {ref,"b38349274fc2bed98d7fe86877e6e1a2df302109"}}, 0}, {<<"aeserialization">>, {git,"https://github.com/aeternity/aeserialization.git", -- 2.30.2 From 1353cebc990051a7150784ef0200921165ac3bb7 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 9 Jun 2023 13:05:00 +0300 Subject: [PATCH 89/92] Remove the getopt dep --- rebar.config | 1 - rebar.lock | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index 202040b..e07433a 100644 --- a/rebar.config +++ b/rebar.config @@ -3,7 +3,6 @@ {erl_opts, [debug_info]}. {deps, [ {aebytecode, {git, "https://github.com/aeternity/aebytecode.git", {tag, "v3.3.0"}}} - , {getopt, "1.0.1"} , {eblake2, "1.0.0"} , {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}} ]}. diff --git a/rebar.lock b/rebar.lock index 7d1705e..7f13b93 100644 --- a/rebar.lock +++ b/rebar.lock @@ -16,7 +16,7 @@ {git,"https://github.com/aeternity/enacl.git", {ref,"793ddb502f7fe081302e1c42227dca70b09f8e17"}}, 2}, - {<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},0}, + {<<"getopt">>,{pkg,<<"getopt">>,<<"1.0.1">>},1}, {<<"jsx">>, {git,"https://github.com/talentdeficit/jsx.git", {ref,"3074d4865b3385a050badf7828ad31490d860df5"}}, -- 2.30.2 From 34920eb467c9acfe94c0228e595ffa6fa48783eb Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 9 Jun 2023 13:34:16 +0300 Subject: [PATCH 90/92] Fix calldata tests --- src/aeso_compiler.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_compiler.erl b/src/aeso_compiler.erl index 3dc3270..1ff6ec3 100644 --- a/src/aeso_compiler.erl +++ b/src/aeso_compiler.erl @@ -186,7 +186,7 @@ check_call(Source, FunName, Args, Options) -> check_call1(ContractString0, FunName, Args, Options) -> case add_extra_call(ContractString0, {call, FunName, Args}, Options) of {ok, CallName, Code} -> - {def, _, FcodeArgs} = get_call_body(CallName, Code), + {def, _, _, FcodeArgs} = get_call_body(CallName, Code), {ok, FunName, [ aeso_fcode_to_fate:term_to_fate(A) || A <- FcodeArgs ]}; Err = {error, _} -> Err -- 2.30.2 From 3ea11105b445579324ab52f4772b7d8b78eb307c Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 9 Jun 2023 13:38:51 +0300 Subject: [PATCH 91/92] Remove file committed by mistake --- src/aeso_code_analysis.erl | 214 ------------------------------------- 1 file changed, 214 deletions(-) delete mode 100644 src/aeso_code_analysis.erl diff --git a/src/aeso_code_analysis.erl b/src/aeso_code_analysis.erl deleted file mode 100644 index 5c78f0f..0000000 --- a/src/aeso_code_analysis.erl +++ /dev/null @@ -1,214 +0,0 @@ --module(aeso_code_analysis). - --export([analyze/1]). - -%-record(env, {vars = [] :: list()}). -% -%-type env() :: #env{}. - --record(analysis, - { defined_types = sets:new() :: sets:set() - , defined_funs = sets:new() :: sets:set() - , used_types = sets:new() :: sets:set() - , used_funs = sets:new() :: sets:set() - , used_includes = sets:new() :: sets:set() - , unused_stateful = sets:new() :: sets:set() - %, used_vars = [] :: list() - %, defined_vars = [] :: list() - %, used_consts = [] :: list() - %, shadowing_pairs = [] :: list() - %, unused_retval = [] :: list() - }). - -%-type analysis() :: #analysis{}. - --define(P(X), io:format(??X ++ ":\n~p\n", [X])). - --record(alg, - { zero :: A - , plus :: fun((A, A) -> A) - , scoped :: fun((A, A) -> A) }). - -work(expr, X = {qid, Ann, Fun}) -> - ?P(X), - ?P(aeso_syntax:get_ann(stateful, Ann, none)), - ?P(""), - #analysis{used_funs = sets:from_list([Fun])}; -work(type, {qid, _, Type}) -> - #analysis{used_types = sets:from_list([Type])}; -work(bind_type, {id, _, Type}) -> - #analysis{defined_types = sets:from_list([Type])}; -work(_, _) -> - #analysis{}. - --spec analyze(aeso_syntax:ast()) -> ok. -analyze([{Contract, _Ann, {con, _, _ConName}, _Impls, Decls} | Rest]) - when Contract == contract_main; - Contract == contract_child -> - analyze_contract(Decls), - analyze(Rest); -analyze([{namespace, _Ann, {con, _, _NSName}, Decls} | Rest]) -> - analyze_contract(Decls), - analyze(Rest); -analyze([]) -> - error("End of code analysis"). - -analyze_contract(Decls) -> - Funs = [ Fun || Fun = {letfun, _, _, _, _, _} <- Decls], - _Types = [ Def || Def = {type_def, _, _, _, _} <- Decls ], - _Consts = [ Const || Const = {letval, _, _, _} <- Decls ], - - Alg = - #alg{ zero = #analysis{} - , plus = fun merge/2 - , scoped = fun merge/2 }, - Res0 = aeso_syntax_utils:fold( - Alg, - fun work/2, - decl, - Decls), - Res = merge(Res0, #analysis{defined_funs = Funs}), - UsedTypes = sets:to_list(Res#analysis.used_types), - UsedFuns = sets:to_list(Res#analysis.used_funs), - ?P(UsedFuns), - ?P(UsedTypes), - - %Res = [ {Name, analyze_fun(Fun)} || Fun = {letfun, _, {id, _, Name}, _, _, _} <- Funs ], - - ?P(Res). -% -%analyze_fun({letfun, _, _FunId, _Args, _, GuardedBodies}) -> -% lists:foldl(fun merge/2, #analysis{}, [(analyze_expr(#env{}, Body)) || {guarded, _, _, Body} <- GuardedBodies ]). -% -%-spec analyze_expr(env(), aeso_syntax:expr()) -> analysis(). -%analyze_expr(Env, {lam, _, Args, Expr}) -> -% NewVars = [ Id || {arg, _, Id, _} <- Args ], -% Env1 = lists:foldl(fun bind_var/2, Env, NewVars), -% Analysis = analyze_expr(Env1, Expr), -% Analysis#analysis{defined_vars = Analysis#analysis.defined_vars ++ NewVars}; -%%analyze_expr(Env, {'if', ann(), expr(), expr(), expr()}) -> -%% ok; -%%analyze_expr(Env, {switch, ann(), expr(), [alt()]}) -> -%% ok; -%analyze_expr(Env, {app, _, Expr, _Args}) -> -% analyze_expr(Env, Expr); -%%analyze_expr(Env, {proj, ann(), expr(), id()}) -> -%% ok; -%analyze_expr(Env, {tuple, _, Exprs}) -> -% lists:foldl(fun merge/2, #analysis{}, [ analyze_expr(Env, Expr) || Expr <- Exprs ]); -%%analyze_expr(Env, {list, ann(), [expr()]}) -> -%% ok; -%%analyze_expr(Env, {list_comp, ann(), expr(), [comprehension_exp()]}) -> -%% ok; -%analyze_expr(Env, {typed, _, Expr, Type}) -> -% merge(analyze_expr(Env, Expr), analyze_type(Env, Type)); -%%analyze_expr(Env, {record_or_map(), ann(), [field(expr())]}) -> -%% ok; -%%analyze_expr(Env, {record_or_map(), ann(), expr(), [field(expr())]}) -> -%% ok; -%%analyze_expr(Env, {map, ann(), [{expr(), expr()}]}) -> -%% ok; -%%analyze_expr(Env, {map_get, ann(), expr(), expr()}) -> -%% ok; -%%analyze_expr(Env, {map_get, ann(), expr(), expr(), expr()}) -> -%% ok; -%analyze_expr(Env, {block, _, Stmts}) -> -% analyze_block(Env, Stmts); -%%analyze_expr(Env, {op(), ann()}) -> -%% ok; -%analyze_expr(_Env, {int, _, _}) -> -% #analysis{}; -%analyze_expr(Env, Id = {id, _, _}) -> -% #analysis{used_vars = [lookup_var(Id, Env)]}; -%analyze_expr(_Env, {qcon, _, _}) -> -% #analysis{}. -%%analyze_expr(Env, QId = {qid, _, _}) -> -%% #analysis{used_funs = lookup_fun(QId, Env)}. -%%analyze_expr(Env, qid() | con() | qcon()) -> -%% ok; -%%analyze_expr(Env, constant()) -> -%% ok; -%%analyze_expr(Env, letpat()) -> -%% ok. -% -%analyze_block(_Env, []) -> -% #analysis{}; -%analyze_block(Env, [E]) -> -% analyze_expr(Env, E); -%analyze_block(Env, [{letval, _, {typed, _, Id = {id, _, _}, _}, Expr} | Stmts]) -> -% Env1 = bind_var(Id, Env), -% Analysis = analyze_block(Env1, Stmts), -% Analysis2 = merge(Analysis, analyze_expr(Env1, Expr)), -% Analysis2#analysis{defined_vars = Analysis2#analysis.defined_vars ++ [Id]}. -% -%analyze_type(_Env, {id, _, Id}) -> -% #analysis{used_types = [Id]}; -%analyze_type(_Env, {qid, _, QId}) -> -% #analysis{used_types = [QId]}; -%analyze_type(Env, {fun_t, _, _, Types, Type}) -> -% merge(lists:foldl(fun merge/2, #analysis{}, [analyze_type(Env, T) || T <- Types]), analyze_type(Env, Type)); -%analyze_type(_Env, {tuple_t, _, _}) -> -% #analysis{}. -% -%bind_var(VarId, Env = #env{vars = Vars}) -> -% check_shadowing(VarId, Vars), -% Env#env{vars = [VarId | Vars]}. -% -%check_shadowing(Var = {id, _, VarName}, Ids) -> -% Shadowed = -% lists:search(fun({id, _, Name}) when Name == VarName -> true; -% (_) -> false -% end, Ids), -% case Shadowed of -% false -> -% #analysis{}; -% {value, ShadowedVar} -> -% #analysis{shadowing_pairs = [{Var, ShadowedVar}]} -% end. -% -%lookup_var({id, _, VarName}, Env) -> -% {value, Var}= -% lists:search( -% fun({id, _, Name}) when Name == VarName -> true; -% (_) -> false -% end, Env#env.vars), -% Var. - - -merge(A1, A2) -> - #analysis{ used_types = sets:union(A1#analysis.used_types, A2#analysis.used_types) - , used_funs = sets:union(A1#analysis.used_funs, A2#analysis.used_funs) }. - - -%% the set of unused functions is the different between the 2 sets: -%% - In a contract: -%% * all user-defined functions -%% * all function calls -%% - In a namespace: -%% * all user-defined private functions -%% * all function calls -%% Note: this only applies to functions, not entrypoints - -%% Unused variables: -%% ----------------- -%% Scope: function -%% Algo: if a variable is not used in its current scope, then it's reported. -%% Functions that are declared in one scope but not used, and then declared -%% in a different scope and used, should be considered. -%% -%% Unused stateful: -%% ---------------- -%% Scope: function -%% Algo: check all function calls in the function, if none of them requires -%% stateful, then we say that it's unused. -%% -%% Unused constants: -%% ----------------- -%% Scope: contract or namespace -%% Algo: same as variables, but the scope is fixed to the contract or the namespace. -%% -%% Unused typedefs: -%% ---------------- -%% Scope: contract or namespace -%% Algo: check the types of all expressions in the contract or namespace, if the type -%% doesn't show up anywhere, then the typedef is not used. -- 2.30.2 From 4c7798f84a285fced25a0e9ebaf80f33d6d9dfc0 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Fri, 9 Jun 2023 19:58:33 +0300 Subject: [PATCH 92/92] Remove location anns from contract call type --- src/aeso_ast_infer_types.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index 9514dea..6a71813 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -351,11 +351,11 @@ bind_contract(Typing, {Contract, Ann, Id, _Impls, Contents}, Env) Sys = [{origin, system}], TypeOrFresh = fun({typed, _, _, Type}) -> Type; (_) -> fresh_uvar(Sys) end, Fields = - [ {field_t, AnnF, Entrypoint, contract_call_type(Type)} + [ {field_t, AnnF, Entrypoint, contract_call_type(aeso_syntax:set_ann(Sys, Type))} || {fun_decl, AnnF, Entrypoint, Type = {fun_t, _, _, _, _}} <- Contents ] ++ [ {field_t, AnnF, Entrypoint, contract_call_type( - {fun_t, AnnF, [], [TypeOrFresh(Arg) || Arg <- Args], TypeOrFresh(Ret)}) + {fun_t, Sys, [], [TypeOrFresh(Arg) || Arg <- Args], TypeOrFresh(Ret)}) } || {letfun, AnnF, Entrypoint = {id, _, Name}, Args, _Type, [{guarded, _, [], Ret}]} <- Contents, Name =/= "init" -- 2.30.2