From f8f67ced4791296a1fb2b0e0e82be4a0ec551f26 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Mon, 17 Oct 2022 19:13:37 +0300 Subject: [PATCH] Record real names --- src/aeso_ast_to_fcode.erl | 33 +++++++++++++++++++++++++-------- src/aeso_fcode_to_fate.erl | 38 ++++++++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 1e0138e..d2ff835 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -122,12 +122,13 @@ return := ftype(), body := fexpr() }. --type fcode() :: #{ contract_name := string(), - state_type := ftype(), - state_layout := state_layout(), - event_type := ftype() | none, - functions := #{ fun_name() => fun_def() }, - payable := boolean() }. +-type fcode() :: #{ contract_name := string(), + state_type := ftype(), + state_layout := state_layout(), + event_type := ftype() | none, + functions := #{ fun_name() => fun_def() }, + 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 -> diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 3282790..5f276c0 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -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 -------------------------------------------------------------- @@ -74,10 +81,11 @@ code_error(Err) -> compile(FCode, Options) -> compile(#{}, FCode, Options). compile(ChildContracts, FCode, Options) -> - #{ contract_name := ContractName, - functions := Functions } = FCode, + #{ contract_name := ContractName, + 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]]).