as: convert to module-tagged errors, format_error/1, and error:format/1; improve specs

This commit is contained in:
Mikael Pettersson 2019-08-16 19:06:21 +02:00
parent 5e34a16dec
commit 295a44f67d
8 changed files with 75 additions and 27 deletions

View File

@ -36,8 +36,8 @@ main_(Argv) ->
ok -> halt(0);
{error, _Reason} = Error -> escript_runtime:fatal("~p\n", [Error])
end;
{error, ErrMsg} ->
escript_runtime:errmsg("~s\n", [ErrMsg]),
{error, Reason} ->
escript_runtime:errmsg("~s\n", [error:format(Reason)]),
usage()
end.

View File

@ -21,11 +21,13 @@
-module(assemble).
-export([ tunit/1
, format_error/1
]).
-include("tunit.hrl").
-include_lib("lib/include/pdp10_elf36.hrl").
-spec tunit(#tunit{}) -> {ok, #tunit{}} | {error, {module(), term()}}.
tunit(Tunit) ->
sections(maps:values(Tunit#tunit.sections), Tunit).
@ -47,7 +49,7 @@ section(Section, Tunit) ->
, sh_flags = ?SHF_MERGE bor ?SHF_STRINGS
} -> comment(Section, Tunit);
#section{ name = Name } ->
{error, io_lib:format("don't know how to assemble section ~s", [Name])}
{error, {?MODULE, {cannot_assemble, Name}}}
end.
%% Assemble .comment -----------------------------------------------------------
@ -100,3 +102,9 @@ insn_image(Insn) ->
(Word bsr 18) band 511,
(Word bsr 9) band 511,
Word band 511].
%% Error reporting -------------------------------------------------------------
-spec format_error(term()) -> io_lib:chars().
format_error({cannot_assemble, Name}) ->
io_lib:format("don't know how to assemble section ~s", [Name]).

View File

@ -21,11 +21,13 @@
-module(input).
-export([ files/1
, format_error/1
]).
-include("tunit.hrl").
-include_lib("lib/include/pdp10_elf36.hrl").
-spec files([string()]) -> {ok, #tunit{}} | {error, {module(), term()}}.
files(Files) ->
NewFiles =
case Files of
@ -235,9 +237,11 @@ section_dot_text() -> % ".text"
%% Error reporting -------------------------------------------------------------
%% FIXME: this is duplicated a few times, move it to scan_state.erl
fmterr(ScanState, Fmt, Args) ->
{ok, FileName} = scan_state:filename(ScanState),
{ok, LineNr} = scan_state:linenr(ScanState),
{error, lists:flatten(io_lib:format("file ~s line ~p: " ++ Fmt,
[FileName, LineNr | Args]))}.
{error, {?MODULE, {FileName, LineNr, Fmt, Args}}}.
-spec format_error(term()) -> io_lib:chars().
format_error({FileName, LineNr, Fmt, Args}) ->
io_lib:format("file ~s line ~p: " ++ Fmt, [FileName, LineNr | Args]).

View File

@ -46,6 +46,7 @@
-module(output).
-export([ tunit/2
, format_error/1
]).
-include("tunit.hrl").
@ -64,6 +65,7 @@
, strtab :: #strtab{}
}).
-spec tunit(#tunit{}, string()) -> ok | {error, {module(), term()}}.
tunit(Tunit, File) ->
emit(layout(Tunit), File).
@ -330,7 +332,7 @@ emit(Context, File) ->
emit(Funs, Context, FP, 0)
after pdp10_stdio:fclose(FP)
end;
{error, Reason} -> {error, io_lib:format("opening ~s: ~p", [File, Reason])}
{error, Reason} -> {error, {?MODULE, {cannot_open, File, Reason}}}
end.
emit([], _Context, _FP, _Offset) -> ok;
@ -558,3 +560,9 @@ image_write([H | T], FP) ->
image_write([], _FP) -> ok;
image_write(TByte, FP) when is_integer(TByte), 0 =< TByte, TByte =< 511 ->
pdp10_stdio:fputc(TByte, FP).
%% Error reporting -------------------------------------------------------------
-spec format_error(term()) -> io_lib:chars().
format_error({cannot_open, File, Reason}) ->
io_lib:format("opening ~s: ~s", [File, error:format(Reason)]).

View File

@ -21,12 +21,15 @@
-module(parse).
-export([ stmt/1
, format_error/1
]).
-include("token.hrl").
-include("tunit.hrl").
-include_lib("lib/include/pdp10_opcodes.hrl").
-spec stmt(scan_state:scan_state())
-> {ok, stmt()} | eof | {error, {module(), term()}}.
stmt(ScanState) ->
case scan:token(ScanState) of
{ok, ?T_DOT_FILE} -> dot_file(ScanState);
@ -303,10 +306,13 @@ dot_type(ScanState) ->
badtok(_ScanState, _ErrMsg, {error, _Reason} = Error) -> Error;
badtok(ScanState, ErrMsg, {ok, Token}) ->
fmterr(ScanState, ErrMsg ++ "; current token is ~s", [token:to_string(Token)]).
fmterr(ScanState, ErrMsg ++ "; current token is ~s", [token:format(Token)]).
fmterr(ScanState, Fmt, Args) ->
{ok, FileName} = scan_state:filename(ScanState),
{ok, LineNr} = scan_state:linenr(ScanState),
{error, lists:flatten(io_lib:format("file ~s line ~p: " ++ Fmt,
[FileName, LineNr | Args]))}.
{error, {?MODULE, {FileName, LineNr, Fmt, Args}}}.
-spec format_error(term()) -> io_lib:chars().
format_error({FileName, LineNr, Fmt, Args}) ->
io_lib:format("file ~s line ~p: " ++ Fmt, [FileName, LineNr | Args]).

View File

@ -21,10 +21,13 @@
-module(scan).
-export([ token/1
, format_error/1
]).
-include("token.hrl").
-spec token(scan_state:scan_state())
-> {ok, token()} | {error, {module(), term()}}.
token(ScanState) ->
case scan_state:fgetc(ScanState) of
{error, _Reason} = Error -> Error;
@ -220,11 +223,14 @@ chval(Ch) ->
end.
badchar(ScanState, Ch, Context) ->
ChStr = char_to_string(Ch),
{ok, FileName} = scan_state:filename(ScanState),
{ok, LineNr} = scan_state:linenr(ScanState),
{error, lists:flatten(io_lib:format("~s line ~p: invalid character '~s' ~s",
[FileName, LineNr, ChStr, Context]))}.
{error, {?MODULE, {FileName, LineNr, Ch, Context}}}.
-spec format_error(term()) -> io_lib:chars().
format_error({FileName, LineNr, Ch, Context}) ->
io_lib:format("~s line ~p: invalid character '~s' ~s",
[FileName, LineNr, char_to_string(Ch), Context]).
char_to_string(eof) -> "<EOF>";
char_to_string(Ch) when $\s =< Ch, Ch =< $~ -> [$', Ch, $'];

View File

@ -31,6 +31,7 @@
% meta-data accessors
, filename/1
, linenr/1
, format_error/1
]).
%% gen_server callbacks
@ -52,39 +53,54 @@
, linenr :: pos_integer()
}).
-type scan_state() :: pid().
-export_type([scan_state/0]).
%% API -------------------------------------------------------------------------
-spec fclose(pid()) -> ok | {error, any()}.
-spec fclose(scan_state()) -> ok | {error, {module(), term()}}.
fclose(Pid) ->
gen_server:call(Pid, fclose, infinity).
-spec fgetc(pid()) -> {ok, byte()} | eof | {error, any()}.
-spec fgetc(scan_state()) -> {ok, byte()} | eof | {error, {module(), term()}}.
fgetc(Pid) ->
gen_server:call(Pid, fgetc, infinity).
-spec fopen(string()) -> {ok, pid()} | {error, any()}.
-spec fopen(string()) -> {ok, scan_state()} | {error, {module(), term()}}.
fopen(File) ->
do_fopen(File).
-spec stdin() -> {ok, pid()}.
-spec stdin() -> {ok, scan_state()}.
stdin() ->
do_fopen(stdin).
do_fopen(File) ->
gen_server:start(?MODULE, File, []).
-spec ungetc(byte(), pid()) -> ok | {error, any()}.
-spec ungetc(byte(), scan_state()) -> ok | {error, {module(), term()}}.
ungetc(Ch, Pid) ->
gen_server:call(Pid, {ungetc, Ch}, infinity).
-spec filename(pid()) -> {ok, string()}.
-spec filename(scan_state()) -> {ok, string()}.
filename(Pid) ->
gen_server:call(Pid, filename, infinity).
-spec linenr(pid()) -> {ok, pos_integer()}.
-spec linenr(scan_state()) -> {ok, pos_integer()}.
linenr(Pid) ->
gen_server:call(Pid, linenr, infinity).
-spec format_error(term()) -> io_lib:chars().
format_error(Reason) ->
case Reason of
{bad_request, Req} ->
io_lib:format("internal error: bad request: ~p", [Req]);
ungetc ->
"internal error: invalid ungetc";
_ ->
io_lib:format("~p", [Reason])
end.
%% gen_server callbacks --------------------------------------------------------
init(stdin) ->
@ -92,7 +108,7 @@ init(stdin) ->
init(File) ->
case file:open(File, [raw, read, read_ahead]) of
{ok, IoDev} -> do_init(File, IoDev);
{error, Reason} -> {stop, Reason}
{error, Reason} -> {stop, {file, Reason}}
end.
do_init(FileName, IoDev) ->
@ -115,7 +131,7 @@ handle_call(Req, _From, State) ->
linenr ->
{reply, {ok, State#state.linenr}, State};
_ ->
{reply, {error, {bad_request, Req}}, State}
{reply, {error, {?MODULE, {bad_request, Req}}}, State}
end.
handle_cast(_Req, State) ->
@ -155,7 +171,7 @@ handle_fgetc(State) ->
_ -> State
end};
eof -> {eof, State};
{error, _Reason} = Error -> {Error, State}
{error, Reason} -> {{error, {file, Reason}}, State}
end,
{reply, Result, NewState};
Ch ->
@ -167,5 +183,5 @@ handle_fgetc(State) ->
handle_ungetc(State, Ch) ->
case State#state.ungetc of
[] -> {reply, ok, State#state{ungetc = Ch}};
_ -> {reply, {error, ungetc}, State}
_ -> {reply, {error, {?MODULE, ungetc}}, State}
end.

View File

@ -21,7 +21,7 @@
-module(token).
-export([ from_symbol/1
, to_string/1
, format/1
]).
-include("token.hrl").
@ -38,8 +38,8 @@ from_symbol(Name) ->
_ -> {?T_SYMBOL, Name}
end.
-spec to_string(token()) -> string().
to_string(Token) ->
-spec format(token()) -> io_lib:chars().
format(Token) ->
case Token of
?T_DOT_FILE -> ".file";
?T_DOT_GLOBL -> ".globl";