Fixed cyclic includes

This commit is contained in:
radrow 2019-07-16 12:03:07 +02:00
parent d64f41dc13
commit d170dd00eb
5 changed files with 66 additions and 43 deletions

View File

@ -36,6 +36,7 @@
| pp_assembler
| pp_bytecode
| no_code
| no_implicit_stdlib
| {backend, aevm | fate}
| {include, {file_system, [string()]} |
{explicit_files, #{string() => binary()}}}

View File

@ -6,6 +6,7 @@
-export([string/1,
string/2,
string/3,
type/1]).
-include("aeso_parse_lib.hrl").
@ -16,13 +17,25 @@
-spec string(string()) -> parse_result().
string(String) ->
string(String, []).
string(String, sets:new(), []).
-spec string(string(), aeso_compiler:options()) -> parse_result().
-spec string(string(), compiler:options()) -> parse_result().
string(String, Opts) ->
string(String, sets:new(), Opts).
-spec string(string(), sets:set(string()), aeso_compiler:options()) -> parse_result().
string(String, Included, Opts) ->
case parse_and_scan(file(), String, Opts) of
{ok, AST} ->
expand_includes(AST, Opts);
STD = case lists:member(no_implicit_stdlib, Opts) of
false -> [{ include, [{src_file, File}, {origin, system}]
, {string, [{src_file, File}, {origin, system}], File}}
|| {File, _} <- aeso_stdlib:stdlib_list()
];
true -> []
end,
expand_includes(STD ++ AST, Included, Opts);
Err = {error, _} ->
Err
end.
@ -230,7 +243,7 @@ exprAtom() ->
, {bool, keyword(false), false}
, ?LET_P(Fs, brace_list(?LAZY_P(field_assignment())), record(Fs))
, {list, [], bracket_list(Expr)}
, ?RULE(keyword('['), Expr, tok('|'), comma_sep(?LAZY_P(comprehension_bind())), tok(']'), list_comp_e(_1, _2, _4))
, ?RULE(keyword('['), Expr, token('|'), comma_sep(?LAZY_P(comprehension_bind())), tok(']'), list_comp_e(_1, _2, _4))
, ?RULE(tok('['), Expr, binop('..'), Expr, tok(']'), _3(_2, _4))
, ?RULE(keyword('('), comma_sep(Expr), tok(')'), tuple_e(_1, _2))
])
@ -527,35 +540,40 @@ bad_expr_err(Reason, E) ->
prettypr:nest(2, aeso_pretty:expr(E))])).
%% -- Helper functions -------------------------------------------------------
expand_includes(AST, Opts) ->
expand_includes(AST, [], Opts).
expand_includes(AST, Included, Opts) ->
expand_includes(AST, Included, [], Opts).
expand_includes([], Acc, _Opts) ->
expand_includes([], _Included, Acc, _Opts) ->
{ok, lists:reverse(Acc)};
expand_includes([{include, Ann, S = {string, _, File}} | AST], Acc, Opts) ->
case {read_file(File, Opts), maps:find(File, aeso_stdlib:stdlib())} of
{{ok, _}, {ok,_ }} ->
return_error(ann_pos(Ann), "Illegal redefinition of standard library " ++ File);
{_, {ok, Lib}} ->
case string(Lib) of
{ok, AST1} ->
expand_includes(AST1 ++ AST, Acc, Opts);
Err = {error, _} ->
Err
end;
{{ok, Bin}, _} ->
expand_includes([{include, Ann, S = {string, _, File}} | AST], Included, Acc, Opts) ->
case sets:is_element(File, Included) of
false ->
Opts1 = lists:keystore(src_file, 1, Opts, {src_file, File}),
case string(binary_to_list(Bin), Opts1) of
{ok, AST1} ->
expand_includes(AST1 ++ AST, Acc, Opts);
Err = {error, _} ->
Err
Included1 = sets:add_element(File, Included),
case {read_file(File, Opts), maps:find(File, aeso_stdlib:stdlib())} of
{{ok, _}, {ok,_ }} ->
return_error(ann_pos(Ann), "Illegal redefinition of standard library " ++ File);
{_, {ok, Lib}} ->
case string(Lib, Included1, Opts1) of
{ok, AST1} ->
expand_includes(AST1 ++ AST, Included1, Acc, Opts);
Err = {error, _} ->
Err
end;
{{ok, Bin}, _} ->
case string(binary_to_list(Bin), Included1, Opts1) of
{ok, AST1} ->
expand_includes(AST1 ++ AST, Included1, Acc, Opts);
Err = {error, _} ->
Err
end;
{_, _} ->
{error, {get_pos(S), include_error, File}}
end;
{{error, _}, _} ->
{error, {get_pos(S), include_error, File}}
true -> expand_includes(AST, Included, Acc, Opts)
end;
expand_includes([E | AST], Acc, Opts) ->
expand_includes(AST, [E | Acc], Opts).
expand_includes([E | AST], Included, Acc, Opts) ->
expand_includes(AST, Included, [E | Acc], Opts).
read_file(File, Opts) ->
case proplists:get_value(include, Opts, {explicit_files, #{}}) of

View File

@ -10,14 +10,15 @@
-module(aeso_stdlib).
-export([stdlib/0]).
-export([stdlib/0, stdlib_list/0]).
stdlib() ->
maps:from_list(
[ {<<"List.aes">>, std_list()}
%% , {<<"Func.aes">>, std_function()}
]
).
maps:from_list(stdlib_list()).
stdlib_list() ->
[ {<<"List.aes">>, std_list()}
%% , {<<"Func.aes">>, std_function()}
].
std_function() ->
"
@ -51,7 +52,8 @@ namespace Func =
".
std_list() ->
"
"namespace List =\n function flat_map() = 3\n".
x() ->"
namespace List =
function empty(l) = switch(l)

View File

@ -9,7 +9,7 @@ simple_aci_test_() ->
test_contract(N) ->
{Contract,MapACI,DecACI} = test_cases(N),
{ok,JSON} = aeso_aci:contract_interface(json, Contract),
{ok,JSON} = aeso_aci:contract_interface(json, Contract, [no_implicit_stdlib]),
?assertEqual([MapACI], JSON),
?assertEqual({ok, DecACI}, aeso_aci:render_aci_json(JSON)).
@ -98,7 +98,7 @@ aci_test_contract(Name) ->
{ok, ContractStub} = aeso_aci:render_aci_json(JSON),
io:format("STUB:\n~s\n", [ContractStub]),
check_stub(ContractStub, [{src_file, Name}]),
check_stub(ContractStub, [{src_file, Name}, no_implicit_stdlib]),
ok.

View File

@ -15,7 +15,7 @@ simple_contracts_test_() ->
?assertMatch(
[{contract, _, {con, _, "Identity"},
[{letfun, _, {id, _, "id"}, [{arg, _, {id, _, "x"}, {id, _, "_"}}], {id, _, "_"},
{id, _, "x"}}]}], parse_string(Text)),
{id, _, "x"}}]}], parse_string(Text, [no_implicit_stdlib])),
ok
end},
{"Operator precedence test.",
@ -71,21 +71,23 @@ parse_contract(Name) ->
roundtrip_contract(Name) ->
round_trip(aeso_test_utils:read_contract(Name)).
parse_string(Text) ->
case aeso_parser:string(Text) of
parse_string(Text) -> parse_string(Text, []).
parse_string(Text, Opts) ->
case aeso_parser:string(Text, Opts) of
{ok, Contract} -> Contract;
Err -> error(Err)
end.
parse_expr(Text) ->
[{letval, _, _, _, Expr}] =
parse_string("let _ = " ++ Text),
parse_string("let _ = " ++ Text, [no_implicit_stdlib]),
Expr.
round_trip(Text) ->
Contract = parse_string(Text),
Contract = parse_string(Text, [no_implicit_stdlib]),
Text1 = prettypr:format(aeso_pretty:decls(Contract)),
Contract1 = parse_string(Text1),
Contract1 = parse_string(Text1, [no_implicit_stdlib]),
NoSrcLoc = remove_line_numbers(Contract),
NoSrcLoc1 = remove_line_numbers(Contract1),
?assertMatch(NoSrcLoc, diff(NoSrcLoc, NoSrcLoc1)).