Properly keep track of src_dir
This commit is contained in:
parent
3ce4e7360c
commit
7f36e980dd
@ -42,6 +42,7 @@
|
|||||||
| {include, {file_system, [string()]} |
|
| {include, {file_system, [string()]} |
|
||||||
{explicit_files, #{string() => binary()}}}
|
{explicit_files, #{string() => binary()}}}
|
||||||
| {src_file, string()}
|
| {src_file, string()}
|
||||||
|
| {src_dir, string()}
|
||||||
| {aci, aeso_aci:aci_type()}.
|
| {aci, aeso_aci:aci_type()}.
|
||||||
-type options() :: [option()].
|
-type options() :: [option()].
|
||||||
|
|
||||||
@ -87,7 +88,9 @@ file(Filename) ->
|
|||||||
file(File, Options0) ->
|
file(File, Options0) ->
|
||||||
Options = add_include_path(File, Options0),
|
Options = add_include_path(File, Options0),
|
||||||
case read_contract(File) of
|
case read_contract(File) of
|
||||||
{ok, Bin} -> from_string(Bin, [{src_file, File} | Options]);
|
{ok, Bin} ->
|
||||||
|
SrcDir = aeso_utils:canonical_dir(filename:dirname(File)),
|
||||||
|
from_string(Bin, [{src_file, File}, {src_dir, SrcDir} | Options]);
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
Msg = lists:flatten([File,": ",file:format_error(Error)]),
|
Msg = lists:flatten([File,": ",file:format_error(Error)]),
|
||||||
{error, [aeso_errors:new(file_error, Msg)]}
|
{error, [aeso_errors:new(file_error, Msg)]}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
many/1, many1/1, sep/2, sep1/2,
|
many/1, many1/1, sep/2, sep1/2,
|
||||||
infixl/2, infixr/2]).
|
infixl/2, infixr/2]).
|
||||||
|
|
||||||
-export([current_file/0, set_current_file/1,
|
-export([current_file/0, set_current_file/1, current_dir/0, set_current_dir/1,
|
||||||
current_include_type/0, set_current_include_type/1]).
|
current_include_type/0, set_current_include_type/1]).
|
||||||
|
|
||||||
%% -- Types ------------------------------------------------------------------
|
%% -- Types ------------------------------------------------------------------
|
||||||
@ -480,6 +480,13 @@ current_file() ->
|
|||||||
set_current_file(File) ->
|
set_current_file(File) ->
|
||||||
put('$current_file', File).
|
put('$current_file', File).
|
||||||
|
|
||||||
|
%% Current source directory
|
||||||
|
current_dir() ->
|
||||||
|
get('$current_dir').
|
||||||
|
|
||||||
|
set_current_dir(File) ->
|
||||||
|
put('$current_dir', File).
|
||||||
|
|
||||||
add_current_file({L, C}) -> {current_file(), L, C};
|
add_current_file({L, C}) -> {current_file(), L, C};
|
||||||
add_current_file(Pos) -> Pos.
|
add_current_file(Pos) -> Pos.
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
-include("aeso_parse_lib.hrl").
|
-include("aeso_parse_lib.hrl").
|
||||||
-import(aeso_parse_lib, [current_file/0, set_current_file/1,
|
-import(aeso_parse_lib, [current_file/0, set_current_file/1,
|
||||||
|
current_dir/0, set_current_dir/1,
|
||||||
current_include_type/0, set_current_include_type/1]).
|
current_include_type/0, set_current_include_type/1]).
|
||||||
|
|
||||||
-type parse_result() :: aeso_syntax:ast() | {aeso_syntax:ast(), sets:set(include_hash())} | none().
|
-type parse_result() :: aeso_syntax:ast() | {aeso_syntax:ast(), sets:set(include_hash())} | none().
|
||||||
@ -58,6 +59,7 @@ run_parser(P, Inp, Opts) ->
|
|||||||
|
|
||||||
parse_and_scan(P, S, Opts) ->
|
parse_and_scan(P, S, Opts) ->
|
||||||
set_current_file(proplists:get_value(src_file, Opts, no_file)),
|
set_current_file(proplists:get_value(src_file, Opts, no_file)),
|
||||||
|
set_current_dir(proplists:get_value(src_dir, Opts, no_file)),
|
||||||
set_current_include_type(proplists:get_value(include_type, Opts, none)),
|
set_current_include_type(proplists:get_value(include_type, Opts, none)),
|
||||||
case aeso_scan:scan(S) of
|
case aeso_scan:scan(S) of
|
||||||
{ok, Tokens} -> aeso_parse_lib:parse(P, Tokens);
|
{ok, Tokens} -> aeso_parse_lib:parse(P, Tokens);
|
||||||
@ -556,6 +558,7 @@ bracket_list(P) -> brackets(comma_sep(P)).
|
|||||||
-spec pos_ann(ann_line(), ann_col()) -> ann().
|
-spec pos_ann(ann_line(), ann_col()) -> ann().
|
||||||
pos_ann(Line, Col) ->
|
pos_ann(Line, Col) ->
|
||||||
[ {file, current_file()}
|
[ {file, current_file()}
|
||||||
|
, {dir, current_dir()}
|
||||||
, {include_type, current_include_type()}
|
, {include_type, current_include_type()}
|
||||||
, {line, Line}
|
, {line, Line}
|
||||||
, {col, Col} ].
|
, {col, Col} ].
|
||||||
@ -696,7 +699,7 @@ expand_includes([], Included, Acc, Opts) ->
|
|||||||
end;
|
end;
|
||||||
expand_includes([{include, Ann, {string, _SAnn, File}} | AST], Included, Acc, Opts) ->
|
expand_includes([{include, Ann, {string, _SAnn, File}} | AST], Included, Acc, Opts) ->
|
||||||
case get_include_code(File, Ann, Opts) of
|
case get_include_code(File, Ann, Opts) of
|
||||||
{ok, Code} ->
|
{ok, AbsDir, Code} ->
|
||||||
Hashed = hash_include(File, Code),
|
Hashed = hash_include(File, Code),
|
||||||
case sets:is_element(Hashed, Included) of
|
case sets:is_element(Hashed, Included) of
|
||||||
false ->
|
false ->
|
||||||
@ -706,9 +709,10 @@ expand_includes([{include, Ann, {string, _SAnn, File}} | AST], Included, Acc, Op
|
|||||||
_ -> indirect
|
_ -> indirect
|
||||||
end,
|
end,
|
||||||
Opts1 = lists:keystore(src_file, 1, Opts, {src_file, File}),
|
Opts1 = lists:keystore(src_file, 1, Opts, {src_file, File}),
|
||||||
Opts2 = lists:keystore(include_type, 1, Opts1, {include_type, IncludeType}),
|
Opts2 = lists:keystore(src_dir, 1, Opts1, {src_dir, AbsDir}),
|
||||||
|
Opts3 = lists:keystore(include_type, 1, Opts2, {include_type, IncludeType}),
|
||||||
Included1 = sets:add_element(Hashed, Included),
|
Included1 = sets:add_element(Hashed, Included),
|
||||||
case parse_and_scan(file(), Code, Opts2) of
|
case parse_and_scan(file(), Code, Opts3) of
|
||||||
{ok, AST1} ->
|
{ok, AST1} ->
|
||||||
expand_includes(AST1 ++ AST, Included1, Acc, Opts);
|
expand_includes(AST1 ++ AST, Included1, Acc, Opts);
|
||||||
Err = {error, _} ->
|
Err = {error, _} ->
|
||||||
@ -726,13 +730,12 @@ expand_includes([E | AST], Included, Acc, Opts) ->
|
|||||||
read_file(File, Opts) ->
|
read_file(File, Opts) ->
|
||||||
case proplists:get_value(include, Opts, {explicit_files, #{}}) of
|
case proplists:get_value(include, Opts, {explicit_files, #{}}) of
|
||||||
{file_system, Paths} ->
|
{file_system, Paths} ->
|
||||||
CandidateNames = [ filename:join(Dir, File) || Dir <- Paths ],
|
lists:foldr(fun(Path, {error, _}) -> read_file_(Path, File);
|
||||||
lists:foldr(fun(F, {error, _}) -> file:read_file(F);
|
(_Path, OK) -> OK end, {error, not_found}, Paths);
|
||||||
(_F, OK) -> OK end, {error, not_found}, CandidateNames);
|
|
||||||
{explicit_files, Files} ->
|
{explicit_files, Files} ->
|
||||||
case maps:get(binary_to_list(File), Files, not_found) of
|
case maps:get(binary_to_list(File), Files, not_found) of
|
||||||
not_found -> {error, not_found};
|
not_found -> {error, not_found};
|
||||||
Src -> {ok, Src}
|
Src -> {ok, File, Src}
|
||||||
end;
|
end;
|
||||||
escript ->
|
escript ->
|
||||||
try
|
try
|
||||||
@ -741,7 +744,7 @@ read_file(File, Opts) ->
|
|||||||
Archive = proplists:get_value(archive, Sections),
|
Archive = proplists:get_value(archive, Sections),
|
||||||
FileName = binary_to_list(filename:join([aesophia, priv, stdlib, File])),
|
FileName = binary_to_list(filename:join([aesophia, priv, stdlib, File])),
|
||||||
case zip:extract(Archive, [{file_list, [FileName]}, memory]) of
|
case zip:extract(Archive, [{file_list, [FileName]}, memory]) of
|
||||||
{ok, [{_, Src}]} -> {ok, Src};
|
{ok, [{_, Src}]} -> {ok, escript, Src};
|
||||||
_ -> {error, not_found}
|
_ -> {error, not_found}
|
||||||
end
|
end
|
||||||
catch _:_ ->
|
catch _:_ ->
|
||||||
@ -749,6 +752,13 @@ read_file(File, Opts) ->
|
|||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
read_file_(Path, File) ->
|
||||||
|
AbsFile = filename:join(Path, File),
|
||||||
|
case file:read_file(AbsFile) of
|
||||||
|
{ok, Bin} -> {ok, aeso_utils:canonical_dir(filename:dirname(AbsFile)), Bin};
|
||||||
|
Err -> Err
|
||||||
|
end.
|
||||||
|
|
||||||
stdlib_options() ->
|
stdlib_options() ->
|
||||||
StdLibDir = aeso_stdlib:stdlib_include_path(),
|
StdLibDir = aeso_stdlib:stdlib_include_path(),
|
||||||
case filelib:is_dir(StdLibDir) of
|
case filelib:is_dir(StdLibDir) of
|
||||||
@ -760,30 +770,29 @@ get_include_code(File, Ann, Opts) ->
|
|||||||
%% Temporarily extend include paths with the directory of the current file
|
%% Temporarily extend include paths with the directory of the current file
|
||||||
Opts1 = include_current_file_dir(Opts, Ann),
|
Opts1 = include_current_file_dir(Opts, Ann),
|
||||||
case {read_file(File, Opts1), read_file(File, stdlib_options())} of
|
case {read_file(File, Opts1), read_file(File, stdlib_options())} of
|
||||||
{{ok, Bin}, {ok, _}} ->
|
{{ok, Dir, Bin}, {ok, _}} ->
|
||||||
case filename:basename(File) == File of
|
case filename:basename(File) == File of
|
||||||
true -> { error
|
true -> { error
|
||||||
, fail( ann_pos(Ann)
|
, fail( ann_pos(Ann)
|
||||||
, "Illegal redefinition of standard library " ++ binary_to_list(File))};
|
, "Illegal redefinition of standard library " ++ binary_to_list(File))};
|
||||||
%% If a path is provided then the stdlib takes lower priority
|
%% If a path is provided then the stdlib takes lower priority
|
||||||
false -> {ok, binary_to_list(Bin)}
|
false -> {ok, Dir, binary_to_list(Bin)}
|
||||||
end;
|
end;
|
||||||
{_, {ok, Bin}} ->
|
{_, {ok, _, Bin}} ->
|
||||||
{ok, binary_to_list(Bin)};
|
{ok, stdlib, binary_to_list(Bin)};
|
||||||
{{ok, Bin}, _} ->
|
{{ok, Dir, Bin}, _} ->
|
||||||
{ok, binary_to_list(Bin)};
|
{ok, Dir, binary_to_list(Bin)};
|
||||||
{_, _} ->
|
{_, _} ->
|
||||||
{error, {ann_pos(Ann), include_error, File}}
|
{error, {ann_pos(Ann), include_error, File}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
include_current_file_dir(Opts, Ann) ->
|
include_current_file_dir(Opts, Ann) ->
|
||||||
case {proplists:get_value(file, Ann, undefined),
|
case {proplists:get_value(dir, Ann, undefined),
|
||||||
proplists:get_value(include, Opts, undefined)} of
|
proplists:get_value(include, Opts, undefined)} of
|
||||||
{undefined, _} -> Opts;
|
{undefined, _} -> Opts;
|
||||||
{FromFile, {file_system, Paths}} ->
|
{CurrDir, {file_system, Paths}} ->
|
||||||
BaseDir = aeso_utils:canonical_dir(filename:dirname(FromFile)),
|
case lists:member(CurrDir, Paths) of
|
||||||
case lists:member(BaseDir, Paths) of
|
false -> [{include, {file_system, [CurrDir | Paths]}} | Opts];
|
||||||
false -> [{include, {file_system, [BaseDir | Paths]}} | Opts];
|
|
||||||
true -> Opts
|
true -> Opts
|
||||||
end;
|
end;
|
||||||
{_, _} -> Opts
|
{_, _} -> Opts
|
||||||
|
Loading…
x
Reference in New Issue
Block a user