diff --git a/src/middle/Location.ml b/src/middle/Location.ml index 801f67b7e3..77ffd6d8e3 100644 --- a/src/middle/Location.ml +++ b/src/middle/Location.ml @@ -53,21 +53,23 @@ let context_to_string (context_cb : unit -> string list) (loc : t) : let empty = {filename= ""; line_num= 0; col_num= 0; included_from= None} -(** If printed_filename is passed, it will replace the filename printed for - this Location.t and all recursively included ones. +(** +Format the location for error messaging. + +If printed_filename is passed, it replaces the highest-level name and +leaves the filenames of included files intact. *) let rec to_string ?printed_filename ?(print_file = true) ?(print_line = true) loc = let open Format in - let filename = - match printed_filename with None -> loc.filename | Some f -> f in - let file = if print_file then sprintf "'%s', " filename else "" in - let line = if print_line then sprintf "line %d, " loc.line_num else "" in - let incl = + let incl, filename = match loc.included_from with | Some loc2 -> - sprintf ", included from\n%s" (to_string ?printed_filename loc2) - | None -> "" in + ( sprintf ", included from\n%s" (to_string ?printed_filename loc2) + , loc.filename ) + | None -> ("", Option.value ~default:loc.filename printed_filename) in + let file = if print_file then sprintf "'%s', " filename else "" in + let line = if print_line then sprintf "line %d, " loc.line_num else "" in sprintf "%s%scolumn %d%s" file line loc.col_num incl let compare loc1 loc2 = diff --git a/src/stanc/stanc.ml b/src/stanc/stanc.ml index 4fa81128d5..49a137359e 100644 --- a/src/stanc/stanc.ml +++ b/src/stanc/stanc.ml @@ -254,15 +254,17 @@ let get_ast_or_exit ?printed_filename ?(print_warnings = true) (Warnings.pp_warnings ?printed_filename) Fmt.stderr warnings ; match res with | Result.Ok ast -> ast - | Result.Error err -> Errors.pp Fmt.stderr err ; exit 1 + | Result.Error err -> + Errors.pp ?printed_filename Fmt.stderr err ; + exit 1 -let type_ast_or_exit ast = +let type_ast_or_exit ?printed_filename ast = match Typechecker.check_program ast with | Result.Ok (p, warns) -> - Warnings.pp_warnings Fmt.stderr warns ; + Warnings.pp_warnings ?printed_filename Fmt.stderr warns ; p | Result.Error error -> - Errors.pp_semantic_error Fmt.stderr error ; + Errors.pp_semantic_error ?printed_filename Fmt.stderr error ; exit 1 (* @@ -280,14 +282,16 @@ let print_or_write data = else print_endline data let use_file filename = + let printed_filename = + match !filename_for_msg with "" -> None | s -> Some s in let ast = - get_ast_or_exit filename + get_ast_or_exit ?printed_filename filename ~print_warnings:(not !canonicalize_settings.deprecations) ~bare_functions:!bare_functions in (* must be before typecheck to fix up deprecated syntax which gets rejected *) let ast = Canonicalize.repair_syntax ast !canonicalize_settings in Debugging.ast_logger ast ; - let typed_ast = type_ast_or_exit ast in + let typed_ast = type_ast_or_exit ?printed_filename ast in let canonical_ast = Canonicalize.canonicalize_program typed_ast !canonicalize_settings in if !pretty_print_program then @@ -298,8 +302,6 @@ let use_file filename = if !print_info_json then ( print_endline (Info.info canonical_ast) ; exit 0 ) ; - let printed_filename = - match !filename_for_msg with "" -> None | s -> Some s in if not !canonicalize_settings.deprecations then Warnings.pp_warnings Fmt.stderr ?printed_filename (Deprecation_analysis.collect_warnings typed_ast) ; diff --git a/test/integration/cli-args/dune b/test/integration/cli-args/dune index c551990dfd..0bfdda28e7 100644 --- a/test/integration/cli-args/dune +++ b/test/integration/cli-args/dune @@ -1,39 +1,3 @@ -(rule - (targets filename_error.output) - (deps - (package stanc) - filename_error.stan) - (action - (with-stdout-to - %{targets} - (run - %{bin:run_bin_on_args} - "%{bin:stanc} --filename-in-msg=foo.stan " - filename_error.stan)))) - -(rule - (alias runtest) - (action - (diff filename_error.expected filename_error.output))) - -(rule - (targets filename_good.output) - (deps - (package stanc) - filename_good.stan) - (action - (with-stdout-to - %{targets} - (run - %{bin:run_bin_on_args} - "%{bin:stanc} --filename-in-msg=foo.stan --print-cpp " - filename_good.stan)))) - -(rule - (alias runtest) - (action - (diff filename_good.expected filename_good.output))) - (rule (targets notfound.output) (deps diff --git a/test/integration/cli-args/filename-in-msg/dune b/test/integration/cli-args/filename-in-msg/dune new file mode 100644 index 0000000000..353c8f2a57 --- /dev/null +++ b/test/integration/cli-args/filename-in-msg/dune @@ -0,0 +1,35 @@ +(rule + (targets filename_error.output) + (deps + (package stanc) + (:stanfiles filename_error.stan filename_syntax_error.stan includes.stan)) + (action + (with-stdout-to + %{targets} + (run + %{bin:run_bin_on_args} + "%{bin:stanc} --filename-in-msg=foo.stan --include-paths=. " + %{stanfiles})))) + +(rule + (alias runtest) + (action + (diff filename_error.expected filename_error.output))) + +(rule + (targets filename_good.output) + (deps + (package stanc) + filename_good.stan) + (action + (with-stdout-to + %{targets} + (run + %{bin:run_bin_on_args} + "%{bin:stanc} --filename-in-msg=foo.stan --print-cpp " + filename_good.stan)))) + +(rule + (alias runtest) + (action + (diff filename_good.expected filename_good.output))) diff --git a/test/integration/cli-args/filename-in-msg/filename_error.expected b/test/integration/cli-args/filename-in-msg/filename_error.expected new file mode 100644 index 0000000000..b706b8f1ef --- /dev/null +++ b/test/integration/cli-args/filename-in-msg/filename_error.expected @@ -0,0 +1,30 @@ + $ ../../../../../install/default/bin/stanc --filename-in-msg=foo.stan --include-paths=. filename_error.stan +Semantic error in 'foo.stan', line 3, column 17 to column 18: + ------------------------------------------------- + 1: transformed data { + 2: real p; + 3: real q = p + a; + ^ + 4: } + ------------------------------------------------- + +Identifier 'a' not in scope. + $ ../../../../../install/default/bin/stanc --filename-in-msg=foo.stan --include-paths=. filename_syntax_error.stan +Syntax error in 'foo.stan', line 2, column 4 to column 5, parsing error: + ------------------------------------------------- + 1: model { + 2: rea x = 3; + ^ + ------------------------------------------------- + +Ill-formed statement or expression. A statement or expression could be expected here. + $ ../../../../../install/default/bin/stanc --filename-in-msg=foo.stan --include-paths=. includes.stan +Syntax error in './filename_syntax_error.stan', line 2, column 4, included from +'foo.stan', line 6, column 0, parsing error: + ------------------------------------------------- + 1: model { + 2: rea x = 3; + ^ + ------------------------------------------------- + +Ill-formed statement or expression. A statement or expression could be expected here. diff --git a/test/integration/cli-args/filename_error.stan b/test/integration/cli-args/filename-in-msg/filename_error.stan similarity index 100% rename from test/integration/cli-args/filename_error.stan rename to test/integration/cli-args/filename-in-msg/filename_error.stan diff --git a/test/integration/cli-args/filename_good.expected b/test/integration/cli-args/filename-in-msg/filename_good.expected similarity index 99% rename from test/integration/cli-args/filename_good.expected rename to test/integration/cli-args/filename-in-msg/filename_good.expected index 91e1181dac..0cb2128aba 100644 --- a/test/integration/cli-args/filename_good.expected +++ b/test/integration/cli-args/filename-in-msg/filename_good.expected @@ -1,4 +1,4 @@ - $ ../../../../install/default/bin/stanc --filename-in-msg=foo.stan --print-cpp filename_good.stan + $ ../../../../../install/default/bin/stanc --filename-in-msg=foo.stan --print-cpp filename_good.stan // Code generated by %%NAME%% %%VERSION%% #include diff --git a/test/integration/cli-args/filename_good.stan b/test/integration/cli-args/filename-in-msg/filename_good.stan similarity index 100% rename from test/integration/cli-args/filename_good.stan rename to test/integration/cli-args/filename-in-msg/filename_good.stan diff --git a/test/integration/cli-args/filename-in-msg/filename_syntax_error.stan b/test/integration/cli-args/filename-in-msg/filename_syntax_error.stan new file mode 100644 index 0000000000..b2edc8fa8a --- /dev/null +++ b/test/integration/cli-args/filename-in-msg/filename_syntax_error.stan @@ -0,0 +1,2 @@ +model { +rea x = 3; diff --git a/test/integration/cli-args/filename-in-msg/includes.stan b/test/integration/cli-args/filename-in-msg/includes.stan new file mode 100644 index 0000000000..b0398c433c --- /dev/null +++ b/test/integration/cli-args/filename-in-msg/includes.stan @@ -0,0 +1,6 @@ + +data { + +} + +#include "filename_syntax_error.stan" diff --git a/test/integration/cli-args/filename_error.expected b/test/integration/cli-args/filename_error.expected deleted file mode 100644 index c7ca3a4d13..0000000000 --- a/test/integration/cli-args/filename_error.expected +++ /dev/null @@ -1,11 +0,0 @@ - $ ../../../../install/default/bin/stanc --filename-in-msg=foo.stan filename_error.stan -Semantic error in 'filename_error.stan', line 3, column 17 to column 18: - ------------------------------------------------- - 1: transformed data { - 2: real p; - 3: real q = p + a; - ^ - 4: } - ------------------------------------------------- - -Identifier 'a' not in scope.