Record real names

This commit is contained in:
Gaith Hallak 2022-10-17 19:13:37 +03:00
parent 49200a6c55
commit f8f67ced47
2 changed files with 49 additions and 22 deletions

View File

@ -127,7 +127,8 @@
state_layout := state_layout(),
event_type := ftype() | none,
functions := #{ fun_name() => fun_def() },
payable := boolean() }.
payable := boolean(),
saved_fresh_names := #{ var_name() => var_name() } }.
-type type_def() :: fun(([ftype()]) -> ftype()).
@ -171,6 +172,7 @@
-spec ast_to_fcode(aeso_syntax:ast(), [option()]) -> {env(), fcode()}.
ast_to_fcode(Code, Options) ->
init_fresh_names(),
init_saved_fresh_names(),
{Env1, FCode1} = to_fcode(init_env(Options), Code),
FCode2 = optimize(FCode1, Options),
Env2 = Env1#{ child_con_env :=
@ -178,8 +180,10 @@ ast_to_fcode(Code, Options) ->
fun (_, FC) -> optimize(FC, Options) end,
maps:get(child_con_env, Env1)
)},
FCode3 = FCode2#{saved_fresh_names => get(saved_fresh_names)},
clear_fresh_names(),
{Env2, FCode2}.
clear_saved_fresh_names(),
{Env2, FCode3}.
optimize(FCode1, Options) ->
Verbose = lists:member(pp_fcode, Options),
@ -1734,6 +1738,19 @@ init_fresh_names() ->
clear_fresh_names() ->
erase('%fresh').
init_saved_fresh_names() ->
put(saved_fresh_names, #{}).
clear_saved_fresh_names() ->
erase(saved_fresh_names).
-spec fresh_name_save(string()) -> var_name().
fresh_name_save(Name) ->
Fresh = fresh_name(),
Old = get(saved_fresh_names),
New = put(saved_fresh_names, Old#{Fresh => Name}),
Fresh.
-spec fresh_name() -> var_name().
fresh_name() -> fresh_name("%").
@ -1862,7 +1879,7 @@ bottom_up(F, Env, Expr) ->
(_) -> true end,
case ShouldFreshen(X) of
true ->
Z = fresh_name(),
Z = fresh_name_save(X),
Env1 = Env#{ Z => E1 },
{'let', Z, E1, bottom_up(F, Env1, rename([{X, Z}], Body))};
false ->

View File

@ -45,7 +45,14 @@
-define(s(N), {store, N}).
-define(void, {var, 9999}).
-record(env, { contract, vars = [], locals = [], current_function, tailpos = true, child_contracts = #{}, options = []}).
-record(env, { contract,
vars = [],
locals = [],
current_function,
tailpos = true,
child_contracts = #{},
saved_fresh_names = #{},
options = [] }).
%% -- Debugging --------------------------------------------------------------
@ -75,9 +82,10 @@ compile(FCode, Options) ->
compile(#{}, FCode, Options).
compile(ChildContracts, FCode, Options) ->
#{ contract_name := ContractName,
functions := Functions } = FCode,
functions := Functions,
saved_fresh_names := SavedFreshNames } = FCode,
try
SFuns = functions_to_scode(ChildContracts, ContractName, Functions, 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)]),
@ -102,33 +110,34 @@ add_child_symbols(ChildContracts, FateCode) ->
Symbols = maps:from_list([ {make_function_id(FName), make_function_name(FName)} || FName <- Funs ]),
aeb_fate_code:update_symbols(FateCode, Symbols).
functions_to_scode(ChildContracts, ContractName, Functions, Options) ->
functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options) ->
FunNames = maps:keys(Functions),
maps:from_list(
[ {make_function_name(Name), function_to_scode(ChildContracts, ContractName, FunNames, Name, Attrs, Args, Body, Type, Options)}
[ {make_function_name(Name), function_to_scode(ChildContracts, ContractName, FunNames, Name, Attrs, Args, Body, Type, SavedFreshNames, Options)}
|| {Name, #{args := Args,
body := Body,
attrs := Attrs,
return := Type}} <- maps:to_list(Functions)]).
function_to_scode(ChildContracts, ContractName, Functions, Name, Attrs0, Args, Body, ResType, Options) ->
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.
Env = init_env(ChildContracts, ContractName, Functions, Name, Args, Options),
Env = init_env(ChildContracts, ContractName, Functions, Name, Args, SavedFreshNames, Options),
[ add_variables_register(Env, Arg, Register) || {Arg, Register} <- Env#env.vars ],
SCode = to_scode(Env, Body),
{Attrs, {ArgTypes, ResType1}, SCode}.
get_variables_registers() ->
case get(variables_registers) of
undefined -> [];
undefined -> #{};
Vs -> Vs
end.
add_variables_register(Env, Name, Register) ->
add_variables_register(Env = #env{saved_fresh_names = SavedFreshNames}, Name, Register) ->
Olds = get_variables_registers(),
New = {Env#env.contract, Env#env.current_function, Name, Register},
put(variables_registers, [New | Olds]).
RealName = maps:get(Name, SavedFreshNames, Name),
New = {Env#env.contract, Env#env.current_function, RealName},
put(variables_registers, Olds#{New => Register}).
-define(tvars, '$tvars').
@ -174,14 +183,15 @@ types_to_scode(Ts) -> lists:map(fun type_to_scode/1, Ts).
%% -- Environment functions --
init_env(ChildContracts, ContractName, FunNames, Name, Args, Options) ->
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 }.
tailpos = true,
saved_fresh_names = SavedFreshNames }.
next_var(#env{ vars = Vars }) ->
1 + lists:max([-1 | [J || {_, {var, J}} <- Vars]]).