Return mapping from variables to registers in fate compilation (#411)
* Return mapping from variables to registers * Fix dialyzer issues * Record real names * Report saved fresh names as part of fcode env * Undo whitespace changes * Fix dialyzer warnings * Formatting fix * Use function names as strings * Manually handle making function names * Update CHANGELOG * Make variables registers optional * Update docs about the new flag * Remove empty saved_fresh_names map from fcode env
This commit is contained in:
parent
d59023a9f4
commit
09638daa90
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
entrypoint spend(x : int) : int = x
|
entrypoint spend(x : int) : int = x
|
||||||
entrypoint f(c : Main) : int = c.spend(10)
|
entrypoint f(c : Main) : int = c.spend(10)
|
||||||
```
|
```
|
||||||
|
- Return a mapping from variables to FATE registers in the compilation output.
|
||||||
### Changed
|
### Changed
|
||||||
### Removed
|
### Removed
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -53,6 +53,8 @@ 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 `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:
|
#### Options to control which compiler optimizations should run:
|
||||||
|
|
||||||
By default all optimizations are turned on, to disable an optimization, it should be
|
By default all optimizations are turned on, to disable an optimization, it should be
|
||||||
|
@ -1487,7 +1487,7 @@ check_reserved_entrypoints(Funs) ->
|
|||||||
check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type = {fun_t, _, _, _, _}}) ->
|
check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type = {fun_t, _, _, _, _}}) ->
|
||||||
Type1 = {fun_t, _, Named, Args, Ret} = check_type(Env, Type),
|
Type1 = {fun_t, _, Named, Args, Ret} = check_type(Env, Type),
|
||||||
TypeSig = {type_sig, Ann, none, Named, Args, Ret},
|
TypeSig = {type_sig, Ann, none, Named, Args, Ret},
|
||||||
register_implementation(Env, Name),
|
register_implementation(Name),
|
||||||
{{Name, TypeSig}, {fun_decl, Ann, Id, Type1}};
|
{{Name, TypeSig}, {fun_decl, Ann, Id, Type1}};
|
||||||
check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type}) ->
|
check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type}) ->
|
||||||
type_error({fundecl_must_have_funtype, Ann, Id, Type}),
|
type_error({fundecl_must_have_funtype, Ann, Id, Type}),
|
||||||
@ -1495,11 +1495,11 @@ check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type}) ->
|
|||||||
|
|
||||||
%% Register the function FunName as implemented by deleting it from the functions
|
%% Register the function FunName as implemented by deleting it from the functions
|
||||||
%% to be implemented table if it is included there, or return true otherwise.
|
%% to be implemented table if it is included there, or return true otherwise.
|
||||||
-spec register_implementation(env(), FunName) -> true | no_return() when
|
-spec register_implementation(FunName) -> true | no_return() when
|
||||||
FunName :: string().
|
FunName :: string().
|
||||||
register_implementation(Env, Name) ->
|
register_implementation(Name) ->
|
||||||
case ets_lookup(functions_to_implement, Name) of
|
case ets_lookup(functions_to_implement, Name) of
|
||||||
[{Name, _, {fun_decl, _, _, DeclType}}] ->
|
[{Name, _, {fun_decl, _, _, _}}] ->
|
||||||
ets_delete(functions_to_implement, Name);
|
ets_delete(functions_to_implement, Name);
|
||||||
[] ->
|
[] ->
|
||||||
true;
|
true;
|
||||||
@ -1509,9 +1509,9 @@ register_implementation(Env, Name) ->
|
|||||||
|
|
||||||
infer_nonrec(Env, LetFun) ->
|
infer_nonrec(Env, LetFun) ->
|
||||||
create_constraints(),
|
create_constraints(),
|
||||||
NewLetFun = {{FunName, FunSig}, _} = infer_letfun(Env, LetFun),
|
NewLetFun = {{FunName, _}, _} = infer_letfun(Env, LetFun),
|
||||||
check_special_funs(Env, NewLetFun),
|
check_special_funs(Env, NewLetFun),
|
||||||
register_implementation(Env, FunName),
|
register_implementation(FunName),
|
||||||
solve_then_destroy_and_report_unsolved_constraints(Env),
|
solve_then_destroy_and_report_unsolved_constraints(Env),
|
||||||
Result = {TypeSig, _} = instantiate(NewLetFun),
|
Result = {TypeSig, _} = instantiate(NewLetFun),
|
||||||
print_typesig(TypeSig),
|
print_typesig(TypeSig),
|
||||||
@ -1541,7 +1541,7 @@ infer_letrec(Env, Defs) ->
|
|||||||
Inferred =
|
Inferred =
|
||||||
[ begin
|
[ begin
|
||||||
Res = {{Name, TypeSig}, _} = infer_letfun(ExtendEnv, LF),
|
Res = {{Name, TypeSig}, _} = infer_letfun(ExtendEnv, LF),
|
||||||
register_implementation(Env, Name),
|
register_implementation(Name),
|
||||||
Got = proplists:get_value(Name, Funs),
|
Got = proplists:get_value(Name, Funs),
|
||||||
Expect = typesig_to_fun_t(TypeSig),
|
Expect = typesig_to_fun_t(TypeSig),
|
||||||
unify(Env, Got, Expect, {check_typesig, Name, Got, Expect}),
|
unify(Env, Got, Expect, {check_typesig, Name, Got, Expect}),
|
||||||
|
@ -159,7 +159,8 @@
|
|||||||
state_layout => state_layout(),
|
state_layout => state_layout(),
|
||||||
context => context(),
|
context => context(),
|
||||||
vars => [var_name()],
|
vars => [var_name()],
|
||||||
functions := #{ fun_name() => fun_def() }
|
functions := #{ fun_name() => fun_def() },
|
||||||
|
saved_fresh_names => #{ var_name() => var_name() }
|
||||||
}.
|
}.
|
||||||
|
|
||||||
-define(HASH_BYTES, 32).
|
-define(HASH_BYTES, 32).
|
||||||
@ -170,7 +171,7 @@
|
|||||||
%% and produces Fate intermediate code.
|
%% and produces Fate intermediate code.
|
||||||
-spec ast_to_fcode(aeso_syntax:ast(), [option()]) -> {env(), fcode()}.
|
-spec ast_to_fcode(aeso_syntax:ast(), [option()]) -> {env(), fcode()}.
|
||||||
ast_to_fcode(Code, Options) ->
|
ast_to_fcode(Code, Options) ->
|
||||||
init_fresh_names(),
|
init_fresh_names(Options),
|
||||||
{Env1, FCode1} = to_fcode(init_env(Options), Code),
|
{Env1, FCode1} = to_fcode(init_env(Options), Code),
|
||||||
FCode2 = optimize(FCode1, Options),
|
FCode2 = optimize(FCode1, Options),
|
||||||
Env2 = Env1#{ child_con_env :=
|
Env2 = Env1#{ child_con_env :=
|
||||||
@ -178,8 +179,13 @@ ast_to_fcode(Code, Options) ->
|
|||||||
fun (_, FC) -> optimize(FC, Options) end,
|
fun (_, FC) -> optimize(FC, Options) end,
|
||||||
maps:get(child_con_env, Env1)
|
maps:get(child_con_env, Env1)
|
||||||
)},
|
)},
|
||||||
clear_fresh_names(),
|
Env3 =
|
||||||
{Env2, FCode2}.
|
case proplists:get_value(debug_info, Options, false) of
|
||||||
|
true -> Env2#{ saved_fresh_names => get(saved_fresh_names) };
|
||||||
|
false -> Env2
|
||||||
|
end,
|
||||||
|
clear_fresh_names(Options),
|
||||||
|
{Env3, FCode2}.
|
||||||
|
|
||||||
optimize(FCode1, Options) ->
|
optimize(FCode1, Options) ->
|
||||||
Verbose = lists:member(pp_fcode, Options),
|
Verbose = lists:member(pp_fcode, Options),
|
||||||
@ -1728,12 +1734,29 @@ resolve_fun(#{ fun_env := Funs, builtins := Builtin } = Env, Q) ->
|
|||||||
{{Fun, Ar}, _} -> {def_u, Fun, Ar}
|
{{Fun, Ar}, _} -> {def_u, Fun, Ar}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
init_fresh_names() ->
|
init_fresh_names(Options) ->
|
||||||
|
proplists:get_value(debug_info, Options, false) andalso init_saved_fresh_names(),
|
||||||
put('%fresh', 0).
|
put('%fresh', 0).
|
||||||
|
|
||||||
clear_fresh_names() ->
|
clear_fresh_names(Options) ->
|
||||||
|
proplists:get_value(debug_info, Options, false) andalso clear_saved_fresh_names(),
|
||||||
erase('%fresh').
|
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(),
|
||||||
|
case get(saved_fresh_names) of
|
||||||
|
undefined -> ok;
|
||||||
|
Old -> put(saved_fresh_names, Old#{Fresh => Name})
|
||||||
|
end,
|
||||||
|
Fresh.
|
||||||
|
|
||||||
-spec fresh_name() -> var_name().
|
-spec fresh_name() -> var_name().
|
||||||
fresh_name() -> fresh_name("%").
|
fresh_name() -> fresh_name("%").
|
||||||
|
|
||||||
@ -1862,7 +1885,7 @@ bottom_up(F, Env, Expr) ->
|
|||||||
(_) -> true end,
|
(_) -> true end,
|
||||||
case ShouldFreshen(X) of
|
case ShouldFreshen(X) of
|
||||||
true ->
|
true ->
|
||||||
Z = fresh_name(),
|
Z = fresh_name_save(X),
|
||||||
Env1 = Env#{ Z => E1 },
|
Env1 = Env#{ Z => E1 },
|
||||||
{'let', Z, E1, bottom_up(F, Env1, rename([{X, Z}], Body))};
|
{'let', Z, E1, bottom_up(F, Env1, rename([{X, Z}], Body))};
|
||||||
false ->
|
false ->
|
||||||
|
@ -112,10 +112,12 @@ from_string(ContractString, Options) ->
|
|||||||
|
|
||||||
from_string1(ContractString, Options) ->
|
from_string1(ContractString, Options) ->
|
||||||
#{ fcode := FCode
|
#{ fcode := FCode
|
||||||
, fcode_env := #{child_con_env := ChildContracts}
|
, fcode_env := FCodeEnv
|
||||||
, folded_typed_ast := FoldedTypedAst
|
, folded_typed_ast := FoldedTypedAst
|
||||||
, warnings := Warnings } = string_to_code(ContractString, Options),
|
, warnings := Warnings } = string_to_code(ContractString, Options),
|
||||||
FateCode = aeso_fcode_to_fate:compile(ChildContracts, FCode, Options),
|
#{ child_con_env := ChildContracts } = FCodeEnv,
|
||||||
|
SavedFreshNames = maps:get(saved_fresh_names, FCodeEnv, #{}),
|
||||||
|
{FateCode, VarsRegs} = aeso_fcode_to_fate:compile(ChildContracts, FCode, SavedFreshNames, Options),
|
||||||
pp_assembler(FateCode, Options),
|
pp_assembler(FateCode, Options),
|
||||||
ByteCode = aeb_fate_code:serialize(FateCode, []),
|
ByteCode = aeb_fate_code:serialize(FateCode, []),
|
||||||
{ok, Version} = version(),
|
{ok, Version} = version(),
|
||||||
@ -128,7 +130,13 @@ from_string1(ContractString, Options) ->
|
|||||||
payable => maps:get(payable, FCode),
|
payable => maps:get(payable, FCode),
|
||||||
warnings => Warnings
|
warnings => Warnings
|
||||||
},
|
},
|
||||||
{ok, maybe_generate_aci(Res, FoldedTypedAst, Options)}.
|
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)}.
|
||||||
|
|
||||||
maybe_generate_aci(Result, FoldedTypedAst, Options) ->
|
maybe_generate_aci(Result, FoldedTypedAst, Options) ->
|
||||||
case proplists:get_value(aci, Options) of
|
case proplists:get_value(aci, Options) of
|
||||||
@ -185,7 +193,7 @@ check_call1(ContractString0, FunName, Args, Options) ->
|
|||||||
#{fcode := OrgFcode
|
#{fcode := OrgFcode
|
||||||
, fcode_env := #{child_con_env := ChildContracts}
|
, fcode_env := #{child_con_env := ChildContracts}
|
||||||
, ast := Ast} = string_to_code(ContractString0, Options),
|
, ast := Ast} = string_to_code(ContractString0, 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
|
%% collect all hashes and compute the first name without hash collision to
|
||||||
SymbolHashes = maps:keys(aeb_fate_code:symbols(FateCode)),
|
SymbolHashes = maps:keys(aeb_fate_code:symbols(FateCode)),
|
||||||
CallName = first_none_match(?CALL_NAME, SymbolHashes,
|
CallName = first_none_match(?CALL_NAME, SymbolHashes,
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(aeso_fcode_to_fate).
|
-module(aeso_fcode_to_fate).
|
||||||
|
|
||||||
-export([compile/2, compile/3, term_to_fate/1, term_to_fate/2]).
|
-export([compile/3, compile/4, term_to_fate/1, term_to_fate/2]).
|
||||||
|
|
||||||
-ifdef(TEST).
|
-ifdef(TEST).
|
||||||
-export([optimize_fun/4, to_basic_blocks/1]).
|
-export([optimize_fun/4, to_basic_blocks/1]).
|
||||||
@ -45,7 +45,14 @@
|
|||||||
-define(s(N), {store, N}).
|
-define(s(N), {store, N}).
|
||||||
-define(void, {var, 9999}).
|
-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 --------------------------------------------------------------
|
%% -- Debugging --------------------------------------------------------------
|
||||||
|
|
||||||
@ -71,19 +78,27 @@ code_error(Err) ->
|
|||||||
%% -- Main -------------------------------------------------------------------
|
%% -- Main -------------------------------------------------------------------
|
||||||
|
|
||||||
%% @doc Main entry point.
|
%% @doc Main entry point.
|
||||||
compile(FCode, Options) ->
|
compile(FCode, SavedFreshNames, Options) ->
|
||||||
compile(#{}, FCode, Options).
|
compile(#{}, FCode, SavedFreshNames, Options).
|
||||||
compile(ChildContracts, FCode, 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,
|
#{ contract_name := ContractName,
|
||||||
functions := Functions } = FCode,
|
functions := Functions } = FCode,
|
||||||
SFuns = functions_to_scode(ChildContracts, ContractName, Functions, Options),
|
SFuns = functions_to_scode(ChildContracts, ContractName, Functions, SavedFreshNames, Options),
|
||||||
SFuns1 = optimize_scode(SFuns, Options),
|
SFuns1 = optimize_scode(SFuns, Options),
|
||||||
FateCode = to_basic_blocks(SFuns1),
|
FateCode = to_basic_blocks(SFuns1),
|
||||||
?debug(compile, Options, "~s\n", [aeb_fate_asm:pp(FateCode)]),
|
?debug(compile, Options, "~s\n", [aeb_fate_asm:pp(FateCode)]),
|
||||||
case proplists:get_value(include_child_contract_symbols, Options, false) of
|
FateCode1 = case proplists:get_value(include_child_contract_symbols, Options, false) of
|
||||||
false -> FateCode;
|
false -> FateCode;
|
||||||
true -> add_child_symbols(ChildContracts, FateCode)
|
true -> add_child_symbols(ChildContracts, FateCode)
|
||||||
end.
|
end,
|
||||||
|
{FateCode1, get_variables_registers()}.
|
||||||
|
|
||||||
make_function_id(X) ->
|
make_function_id(X) ->
|
||||||
aeb_fate_code:symbol_identifier(make_function_name(X)).
|
aeb_fate_code:symbol_identifier(make_function_name(X)).
|
||||||
@ -97,22 +112,43 @@ add_child_symbols(ChildContracts, FateCode) ->
|
|||||||
Symbols = maps:from_list([ {make_function_id(FName), make_function_name(FName)} || FName <- Funs ]),
|
Symbols = maps:from_list([ {make_function_id(FName), make_function_name(FName)} || FName <- Funs ]),
|
||||||
aeb_fate_code:update_symbols(FateCode, Symbols).
|
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),
|
FunNames = maps:keys(Functions),
|
||||||
maps:from_list(
|
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,
|
|| {Name, #{args := Args,
|
||||||
body := Body,
|
body := Body,
|
||||||
attrs := Attrs,
|
attrs := Attrs,
|
||||||
return := Type}} <- maps:to_list(Functions)]).
|
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),
|
{ArgTypes, ResType1} = typesig_to_scode(Args, ResType),
|
||||||
Attrs = Attrs0 -- [stateful], %% Only track private and payable from here.
|
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) ||
|
||||||
|
proplists:get_value(debug_info, Options, false),
|
||||||
|
{Arg, Register} <- Env#env.vars ],
|
||||||
SCode = to_scode(Env, Body),
|
SCode = to_scode(Env, Body),
|
||||||
{Attrs, {ArgTypes, ResType1}, SCode}.
|
{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').
|
-define(tvars, '$tvars').
|
||||||
|
|
||||||
typesig_to_scode(Args, Res) ->
|
typesig_to_scode(Args, Res) ->
|
||||||
@ -157,19 +193,21 @@ types_to_scode(Ts) -> lists:map(fun type_to_scode/1, Ts).
|
|||||||
|
|
||||||
%% -- Environment functions --
|
%% -- 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) ],
|
#env{ vars = [ {X, {arg, I}} || {I, {X, _}} <- with_ixs(Args) ],
|
||||||
contract = ContractName,
|
contract = ContractName,
|
||||||
child_contracts = ChildContracts,
|
child_contracts = ChildContracts,
|
||||||
locals = FunNames,
|
locals = FunNames,
|
||||||
current_function = Name,
|
current_function = Name,
|
||||||
options = Options,
|
options = Options,
|
||||||
tailpos = true }.
|
tailpos = true,
|
||||||
|
saved_fresh_names = SavedFreshNames }.
|
||||||
|
|
||||||
next_var(#env{ vars = Vars }) ->
|
next_var(#env{ vars = Vars }) ->
|
||||||
1 + lists:max([-1 | [J || {_, {var, J}} <- Vars]]).
|
1 + lists:max([-1 | [J || {_, {var, J}} <- Vars]]).
|
||||||
|
|
||||||
bind_var(Name, Var, Env = #env{ vars = 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] }.
|
Env#env{ vars = [{Name, Var} | Vars] }.
|
||||||
|
|
||||||
bind_local(Name, Env) ->
|
bind_local(Name, Env) ->
|
||||||
@ -194,8 +232,9 @@ serialize_contract_code(Env, C) ->
|
|||||||
case maps:get(C, Cache, none) of
|
case maps:get(C, Cache, none) of
|
||||||
none ->
|
none ->
|
||||||
Options = Env#env.options,
|
Options = Env#env.options,
|
||||||
|
SavedFreshNames = Env#env.saved_fresh_names,
|
||||||
FCode = maps:get(C, Env#env.child_contracts),
|
FCode = maps:get(C, Env#env.child_contracts),
|
||||||
FateCode = compile(Env#env.child_contracts, FCode, Options),
|
{FateCode, _} = compile1(Env#env.child_contracts, FCode, SavedFreshNames, Options),
|
||||||
ByteCode = aeb_fate_code:serialize(FateCode, []),
|
ByteCode = aeb_fate_code:serialize(FateCode, []),
|
||||||
{ok, Version} = aeso_compiler:version(),
|
{ok, Version} = aeso_compiler:version(),
|
||||||
OriginalSourceCode = proplists:get_value(original_src, Options, ""),
|
OriginalSourceCode = proplists:get_value(original_src, Options, ""),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user