PT-156466783 namespaces #516

Merged
zxq9 merged 18 commits from PT-156466783-namespaces into master 2019-02-13 23:54:07 +09:00
3 changed files with 38 additions and 27 deletions
Showing only changes of commit aa6d56ce9b - Show all commits

View File

@ -28,8 +28,8 @@
| pp_icode
| pp_assembler
| pp_bytecode
| {include_path, [string()]}
| {allow_include, boolean()}
| {include, {file_system, [string()]} |
{explicit_files, #{string() => binary()}}}
| {src_file, string()}.
-type options() :: [option()].
@ -49,12 +49,13 @@ version() ->
-spec file(string()) -> {ok, map()} | {error, binary()}.
file(Filename) ->
Dir = filename:dirname(Filename),
file(Filename, [{include_path, [Dir]}]).
{ok, Cwd} = file:get_cwd(),
file(Filename, [{include, {file_system, [Cwd, Dir]}}]).
-spec file(string(), options()) -> {ok, map()} | {error, binary()}.
file(File, Options) ->
case read_contract(File) of
{ok, Bin} -> from_string(Bin, [{src_file, File}, {allow_include, true} | Options]);
{ok, Bin} -> from_string(Bin, [{src_file, File} | Options]);
{error, Error} ->
ErrorString = [File,": ",file:format_error(Error)],
{error, join_errors("File errors", [ErrorString], fun(E) -> E end)}
@ -288,10 +289,8 @@ parse(Text, Options) ->
ErrorString = io_lib:format("Ambiguous ~p", [As]),
parse_error(Pos, ErrorString);
%% Include error
{error, {Pos, include_not_allowed}} ->
parse_error(Pos, "includes not allowed in this context");
{error, {Pos, include_error}} ->
parse_error(Pos, "could not find include file")
{error, {Pos, {include_error, File}}} ->
parse_error(Pos, io_lib:format("could not find include file '~s'", [File]))
end.
parse_error(Pos, ErrorString) ->

View File

@ -483,9 +483,8 @@ expand_includes(AST, Opts) ->
expand_includes([], Acc, _Opts) ->
{ok, lists:reverse(Acc)};
expand_includes([{include, S = {string, _, File}} | AST], Acc, Opts) ->
AllowInc = proplists:get_value(allow_include, Opts, false),
case read_file(File, Opts) of
{ok, Bin} when AllowInc ->
{ok, Bin} ->
Opts1 = lists:keystore(src_file, 1, Opts, {src_file, File}),
case string(binary_to_list(Bin), Opts1) of
{ok, AST1} ->
@ -493,17 +492,22 @@ expand_includes([{include, S = {string, _, File}} | AST], Acc, Opts) ->
Err = {error, _} ->
Err
end;
{ok, _} ->
{error, {get_pos(S), include_not_allowed}};
{error, _} ->
{error, {get_pos(S), include_error}}
{error, {get_pos(S), {include_error, File}}}
end;
expand_includes([E | AST], Acc, Opts) ->
expand_includes(AST, [E | Acc], Opts).
read_file(File, Opts) ->
CandidateNames = [File] ++ [ filename:join(Dir, File)
|| Dir <- proplists:get_value(include_path, Opts, []) ],
case proplists:get_value(include, Opts, {explicit_files, #{}}) of
{file_system, Paths} ->
CandidateNames = [ filename:join(Dir, File) || Dir <- Paths ],
lists:foldr(fun(F, {error, _}) -> file:read_file(F);
(_F, OK) -> OK end, {error, not_found}, CandidateNames).
(_F, OK) -> OK end, {error, not_found}, CandidateNames);
{explicit_files, Files} ->
case maps:get(binary_to_list(File), Files, not_found) of
not_found -> {error, not_found};
Src -> {ok, Src}
end
end.

View File

@ -23,7 +23,7 @@ simple_compile_test_() ->
end} || ContractName <- compilable_contracts() ] ++
[ {"Testing error messages of " ++ ContractName,
fun() ->
case compile(ContractName, false) of
case compile(ContractName) of
<<"Type errors\n", ErrorString/binary>> ->
check_errors(lists:sort(ExpectedErrors), ErrorString);
<<"Parse errors\n", ErrorString/binary>> ->
@ -31,6 +31,17 @@ simple_compile_test_() ->
end
end} ||
{ContractName, ExpectedErrors} <- failing_contracts() ] ++
[ {"Testing include with explicit files",
fun() ->
FileSystem = maps:from_list(
[ begin
{ok, Bin} = file:read_file(filename:join([aeso_test_utils:contract_path(), File])),
{File, Bin}
end || File <- ["included.aes", "../contracts/included2.aes"] ]),
#{byte_code := Code1} = compile("include", [{include, {explicit_files, FileSystem}}]),
#{byte_code := Code2} = compile("include"),
?assertMatch(true, Code1 == Code2)
end} ] ++
[ {"Testing deadcode elimination",
fun() ->
#{ byte_code := NoDeadCode } = compile("nodeadcode"),
@ -50,13 +61,12 @@ check_errors(Expect, ErrorString) ->
{Missing, Extra} -> ?assertEqual(Missing, Extra)
end.
compile(Name) -> compile(Name, true).
compile(Name) ->
compile(Name, [{include, {file_system, [aeso_test_utils:contract_path()]}}]).
compile(Name, AllowInc) ->
compile(Name, Options) ->
String = aeso_test_utils:read_contract(Name),
case aeso_compiler:from_string(String, [{include_path, [aeso_test_utils:contract_path()]},
{allow_include, AllowInc},
{src_file, Name}]) of
case aeso_compiler:from_string(String, [{src_file, Name} | Options]) of
{ok, Map} -> Map;
{error, ErrorString} -> ErrorString
end.
@ -201,8 +211,6 @@ failing_contracts() ->
" r.foo : (gas : int, value : int) => Remote.themap\n"
"against the expected type\n"
" (gas : int, value : int) => map(string, int)">>]}
, {"include",
[<<"file include, line 1, column 9: includes not allowed in this context\n">>]}
, {"bad_include_and_ns",
[<<"Include of 'included.aes' at line 2, column 11\nnot allowed, include only allowed at top level.">>,
<<"Nested namespace not allowed\nNamespace 'Foo' at line 3, column 13 not defined at top level.">>]}