% Copyright (C) 2018-2019 Olivier Boudeville
%
% This file is part of the Ceylan-WOOPER library.
%
% This library is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License or
% the GNU General Public License, as they are published by the Free Software
% Foundation, either version 3 of these Licenses, or (at your option)
% any later version.
% You can also redistribute it and/or modify it under the terms of the
% Mozilla Public License, version 1.1 or later.
%
% This library is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU Lesser General Public License and the GNU General Public License
% for more details.
%
% You should have received a copy of the GNU Lesser General Public
% License, of the GNU General Public License and of the Mozilla Public License
% along with this library.
% If not, see and
% .
%
% Creation date: Friday, April 13, 2018
% Author: Olivier Boudeville [olivier (dot) boudeville (at) esperide (dot) com]
% Gathering of internal helpers.
-module(wooper_internals).
-export([ raise_error/1, raise_error/2,
raise_usage_error/1, raise_usage_error/2, raise_usage_error/3,
raise_usage_error/4,
notify_warning/1, notify_warning/2 ]).
% For the ast_transforms record:
-include("ast_transform.hrl").
% Shorthand:
-type ast_transforms() :: ast_transform:ast_transforms().
% To better report errors:
-define( origin_layer, "WOOPER" ).
% We try to distinguish two kinds of errors:
%
% - rather WOOPER-internal ones, maybe not involving a mistake from the user,
% rather uncommon and where a stacktrace might help (raise_error/N); results in
% an exception being thrown
%
% - usage-related ones, where a precise message with hints may help and where
% the WOOPER-based stacktrace is a useless technical detail
% (raise_usage_error/N); results in the compilation aborting
% Raises a (compile-time, rather ad hoc) technical, internal error when applying
% this parse transform, to stop the build on failure and report the actual
% error.
%
-spec raise_error( term() ) -> no_return().
raise_error( ErrorTerm ) ->
raise_error( ErrorTerm, _Context=undefined ).
% Raises a (compile-time, rather ad hoc) technical, internal error, with
% specified source context, when applying this parse transform, to stop the
% build on failure and report the actual error.
%
-spec raise_error( term(), ast_base:source_context() ) -> no_return().
raise_error( ErrorTerm, Context ) ->
ast_utils:raise_error( ErrorTerm, Context, ?origin_layer ).
% Raises a (compile-time, rather ad hoc) user-related error (when no specific
% source context is available), when applying this parse transform, to stop the
% build on failure and report adequately the actual error to the user.
%
-spec raise_usage_error( text_utils:ustring() ) -> no_return().
raise_usage_error( ErrorString ) ->
raise_usage_error( ErrorString, _ErrorFormatValues=[] ).
% Raises a (compile-time, rather ad hoc) user-related error (when no specific
% source context is available), when applying this parse transform, to stop the
% build on failure and report adequately the actual error to the user.
%
-spec raise_usage_error( text_utils:format_string(),
text_utils:format_values() ) -> no_return().
raise_usage_error( ErrorFormatString, ErrorFormatValues ) ->
io:format( "error: " ++ ErrorFormatString ++ "~n", ErrorFormatValues ),
% Almost the only way to stop the processing of the AST:
halt( 6 ).
% Raises a (compile-time, rather ad hoc) user-related error, with specified
% source context, when applying this parse transform, to stop the build on
% failure and report adequately the actual error to the user.
%
-spec raise_usage_error( text_utils:ustring(), ast_transforms(),
ast_base:line() ) -> no_return();
( text_utils:ustring(), wooper:classname(),
ast_base:line() ) -> no_return();
( text_utils:format_string(), text_utils:format_values(),
wooper:classname() ) -> no_return().
raise_usage_error( ErrorString,
#ast_transforms{ transformed_module_name=Classname },
Line ) ->
ExpectedSrcFile = wooper:get_class_filename( Classname ),
% Finally not used, as we do not need here to specify the layer or to print
% a stacktrace:
%
%ast_utils:raise_error( ErrorString, _Context={ ExpectedModFile, Line },
% ?origin_layer ).
io:format( "~s:~B: ~s~n",
[ ExpectedSrcFile, Line, ErrorString ] ),
% Almost the only way to stop the processing of the AST:
halt( 6 );
raise_usage_error( ErrorString, Classname, Line ) when is_atom( Classname ) ->
ExpectedSrcFile = wooper:get_class_filename( Classname ),
io:format( "~s:~B: ~s~n", [ ExpectedSrcFile, Line, ErrorString ] ),
% Almost the only way to stop the processing of the AST:
halt( 6 );
raise_usage_error( ErrorFormatString, ErrorFormatValues, Classname ) ->
ExpectedSrcFile = wooper:get_class_filename( Classname ),
% Cannot target better:
Line = 0,
io:format( "~s:~B: " ++ ErrorFormatString ++ "~n",
[ ExpectedSrcFile, Line | ErrorFormatValues ] ),
% Almost the only way to stop the processing of the AST:
halt( 6 ).
% Raises a (compile-time, rather ad hoc) user-related error, with specified
% source context, when applying this parse transform, to stop the build on
% failure and report the actual error.
%
-spec raise_usage_error( text_utils:format_string(), text_utils:format_values(),
ast_transforms() | wooper:classname(), ast_base:line() ) ->
no_return().
raise_usage_error( ErrorFormatString, ErrorValues, TransformsOrClass, Line ) ->
ErrorString = text_utils:format( ErrorFormatString, ErrorValues ),
raise_usage_error( ErrorString, TransformsOrClass, Line ).
% Notifies a (compile-time, rather ad hoc) warning, with no specific context,
% when applying this parse transform.
%
% Does not stop the build.
%
-spec notify_warning( [ term() ] ) -> basic_utils:void().
notify_warning( Elements ) ->
notify_warning( Elements, _Context=undefined ).
% Notifies a (compile-time, rather ad hoc) warning, with specified context, when
% applying this parse transform.
%
% Does not stop the build.
%
-spec notify_warning( [ term() ], ast_base:form_context() ) ->
basic_utils:void().
notify_warning( Elements, Context ) ->
ast_utils:notify_warning( Elements, Context ).