Skip to content

Commit ba866dc

Browse files
committed
Forward all frontend depwarns to the logging system
Forward all frontend depwarn messages through to the julia logging system for consistency of formatting and dispatch. Deciding whether a depwarn should appear as an thrown error is also now handled outside flisp to keep this decision in one place where possible. Detail: * Ensure that deprecation-message forwards to the logging system. Also include file and line number metadata * Remove jl_parse_depwarn(), flisp *depwarn* and related scheme code as this can be handled on the julia side. * Rename syntax_deprecation_warnings(false) to without_syntax_deprecations, as this was only ever used to turn syntax deprecations off. * Ensure that all lowering depwarns with existing line number information get this passed through as accessible metadata rather than as a string. * Use distinct functions for depwarns coming from the parser vs lowering, as these get line number information in a different way. TODO: * Figure out a decent `id` for the syntax and lowering depwarn messages * Make without_syntax_deprecations filter only depwarn messages, rather than everything!
1 parent 2482202 commit ba866dc

10 files changed

+165
-141
lines changed

base/client.jl

+4-10
Original file line numberDiff line numberDiff line change
@@ -185,16 +185,10 @@ function eval_user_input(@nospecialize(ast), show_value)
185185
isa(STDIN,TTY) && println()
186186
end
187187

188-
syntax_deprecation_warnings(warn::Bool) =
189-
ccall(:jl_parse_depwarn, Cint, (Cint,), warn) == 1
190-
191-
function syntax_deprecation_warnings(f::Function, warn::Bool)
192-
prev = syntax_deprecation_warnings(warn)
193-
try
194-
f()
195-
finally
196-
syntax_deprecation_warnings(prev)
197-
end
188+
function without_syntax_deprecations(f::Function)
189+
# Turn off all logging
190+
# TODO: Disable only depwarns, but in a clean way.
191+
with_logger(f, Logging.NullLogger())
198192
end
199193

200194
function parse_input_line(s::String; filename::String="none")

base/deprecated.jl

+18-2
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,12 @@ macro deprecate(old, new, ex=true)
6262
end
6363
end
6464

65+
# NB: keep in sync with JL_OPTIONS_DEPWARN_THROW
66+
depwarn_should_throw(opts) = opts.depwarn == typemax(Int32)
67+
6568
function depwarn(msg, funcsym)
6669
opts = JLOptions()
67-
if opts.depwarn == typemax(Int32)
70+
if depwarn_should_throw(opts)
6871
throw(ErrorException(msg))
6972
end
7073
deplevel = Logging.LogLevel(opts.depwarn)
@@ -74,7 +77,7 @@ function depwarn(msg, funcsym)
7477
_module=begin
7578
bt = backtrace()
7679
frame, caller = firstcaller(bt, funcsym)
77-
# FIXME - The isnull handling isn't great here.
80+
# FIXME - Which module should a null here be attributed to?
7881
!isnull(caller.linfo) ? caller.linfo.value.def.module : Base
7982
end,
8083
_file=caller.file,
@@ -87,6 +90,19 @@ function depwarn(msg, funcsym)
8790
nothing
8891
end
8992

93+
# Emit deprecated syntax warning. This function exists to be called from
94+
# the julia parser (see flisp julia-syntax-depwarn) and in that context any
95+
# exceptions will be ignored.
96+
function syntax_depwarn(msg, file, line)
97+
opts = JLOptions()
98+
if depwarn_should_throw(opts)
99+
return 2 # Will throw error on parser side to simplify marshalling
100+
end
101+
deplevel = Logging.LogLevel(opts.depwarn)
102+
@logmsg deplevel msg _file=file _line=line _group=:depwarn
103+
return 0
104+
end
105+
90106
firstcaller(bt::Array{Ptr{Void},1}, funcsym::Symbol) = firstcaller(bt, (funcsym,))
91107
function firstcaller(bt::Array{Ptr{Void},1}, funcsyms)
92108
# Identify the calling line

base/docs/utils.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ function helpmode(io::IO, line::AbstractString)
102102
# keyword such as `function` would throw a parse error due to the missing `end`.
103103
Symbol(line)
104104
else
105-
x = Base.syntax_deprecation_warnings(false) do
105+
x = Base.without_syntax_deprecations() do
106106
parse(line, raise = false)
107107
end
108108
# Retrieving docs for macros requires us to make a distinction between the text

base/repl/REPL.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ end
623623
LineEdit.reset_state(hist::REPLHistoryProvider) = history_reset_state(hist)
624624

625625
function return_callback(s)
626-
ast = Base.syntax_deprecation_warnings(false) do
626+
ast = Base.without_syntax_deprecations() do
627627
Base.parse_input_line(String(take!(copy(LineEdit.buffer(s)))))
628628
end
629629
if !isa(ast, Expr) || (ast.head != :continue && ast.head != :incomplete)
@@ -894,7 +894,7 @@ function setup_interface(
894894
continue
895895
end
896896
end
897-
ast, pos = Base.syntax_deprecation_warnings(false) do
897+
ast, pos = Base.without_syntax_deprecations() do
898898
Base.parse(input, oldpos, raise=false)
899899
end
900900
if (isa(ast, Expr) && (ast.head == :error || ast.head == :continue || ast.head == :incomplete)) ||

base/repl/REPLCompletions.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ function complete_symbol(sym, ffunc)
4444
# Find module
4545
lookup_name, name = rsplit(sym, ".", limit=2)
4646

47-
ex = Base.syntax_deprecation_warnings(false) do
47+
ex = Base.without_syntax_deprecations() do
4848
parse(lookup_name, raise=false)
4949
end
5050

@@ -460,7 +460,7 @@ end
460460
function completions(string, pos)
461461
# First parse everything up to the current position
462462
partial = string[1:pos]
463-
inc_tag = Base.syntax_deprecation_warnings(false) do
463+
inc_tag = Base.without_syntax_deprecations() do
464464
Base.incomplete_tag(parse(partial, raise=false))
465465
end
466466

@@ -508,7 +508,7 @@ function completions(string, pos)
508508

509509
if inc_tag == :other && should_method_complete(partial)
510510
frange, method_name_end = find_start_brace(partial)
511-
ex = Base.syntax_deprecation_warnings(false) do
511+
ex = Base.without_syntax_deprecations() do
512512
parse(partial[frange] * ")", raise=false)
513513
end
514514
if isa(ex, Expr) && ex.head==:call

src/ast.c

+34-33
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,47 @@ value_t fl_julia_scalar(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
168168
return fl_ctx->F;
169169
}
170170

171+
static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, jl_module_t *mod);
172+
173+
174+
value_t fl_julia_depwarn(fl_context_t *fl_ctx, value_t *args, uint32_t nargs)
175+
{
176+
if (nargs < 1)
177+
lerror(fl_ctx, fl_ctx->ArgError, "julia-depwarn: too few arguments");
178+
static jl_value_t *depwarn_func = NULL;
179+
if (!depwarn_func && jl_base_module)
180+
depwarn_func = jl_get_global(jl_base_module, jl_symbol("syntax_depwarn"));
181+
if (!depwarn_func) {
182+
// No julia function found - use fallbacks in flisp
183+
return fixnum(jl_options.depwarn == JL_OPTIONS_DEPWARN_THROW ? 2 : 1);
184+
}
185+
value_t ret = fixnum(0);
186+
jl_value_t **depwarn_args;
187+
JL_GC_PUSHARGS(depwarn_args, nargs+2);
188+
JL_TRY {
189+
depwarn_args[0] = depwarn_func;
190+
for (int i = 0; i < nargs; ++i)
191+
depwarn_args[i+1] = scm_to_julia_(fl_ctx, args[i], NULL);
192+
jl_value_t* jlret = jl_apply(depwarn_args, nargs+1);
193+
depwarn_args[nargs+1] = jlret;
194+
ret = julia_to_scm(fl_ctx, jlret);
195+
}
196+
JL_CATCH {
197+
// Internal error on julia side - assume logging failed
198+
ret = fixnum(1);
199+
}
200+
JL_GC_POP();
201+
return ret;
202+
}
203+
171204
static const builtinspec_t julia_flisp_ast_ext[] = {
172205
{ "defined-julia-global", fl_defined_julia_global },
173206
{ "current-julia-module-counter", fl_current_module_counter },
174207
{ "julia-scalar?", fl_julia_scalar },
208+
{ "julia-depwarn", fl_julia_depwarn },
175209
{ NULL, NULL }
176210
};
177211

178-
static int jl_parse_deperror(fl_context_t *fl_ctx, int err);
179-
static int jl_parse_depwarn_(fl_context_t *fl_ctx, int warn);
180-
181212
static void jl_init_ast_ctx(jl_ast_context_t *ast_ctx)
182213
{
183214
fl_context_t *fl_ctx = &ast_ctx->fl;
@@ -201,12 +232,6 @@ static void jl_init_ast_ctx(jl_ast_context_t *ast_ctx)
201232
ctx->slot_sym = symbol(fl_ctx, "slot");
202233
ctx->task = NULL;
203234
ctx->module = NULL;
204-
205-
// Enable / disable syntax deprecation warnings
206-
if (jl_options.depwarn == JL_OPTIONS_DEPWARN_THROW)
207-
jl_parse_deperror(fl_ctx, 1);
208-
else
209-
jl_parse_depwarn_(fl_ctx, (int)jl_options.depwarn);
210235
}
211236

212237
// There should be no GC allocation while holding this lock
@@ -397,8 +422,6 @@ static jl_sym_t *scmsym_to_julia(fl_context_t *fl_ctx, value_t s)
397422
return jl_symbol(symbol_name(fl_ctx, s));
398423
}
399424

400-
static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, jl_module_t *mod);
401-
402425
static jl_value_t *scm_to_julia(fl_context_t *fl_ctx, value_t e, jl_module_t *mod)
403426
{
404427
jl_value_t *v = NULL;
@@ -828,28 +851,6 @@ JL_DLLEXPORT jl_value_t *jl_load_file_string(const char *text, size_t len,
828851
return jl_parse_eval_all(filename, text, len, inmodule);
829852
}
830853

831-
JL_DLLEXPORT int jl_parse_depwarn(int warn)
832-
{
833-
jl_ast_context_t *ctx = jl_ast_ctx_enter();
834-
int res = jl_parse_depwarn_(&ctx->fl, warn);
835-
jl_ast_ctx_leave(ctx);
836-
return res;
837-
}
838-
839-
static int jl_parse_depwarn_(fl_context_t *fl_ctx, int warn)
840-
{
841-
value_t prev = fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, "jl-parser-depwarn")),
842-
warn ? fl_ctx->T : fl_ctx->F);
843-
return prev == fl_ctx->T ? 1 : 0;
844-
}
845-
846-
static int jl_parse_deperror(fl_context_t *fl_ctx, int err)
847-
{
848-
value_t prev = fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, "jl-parser-deperror")),
849-
err ? fl_ctx->T : fl_ctx->F);
850-
return prev == fl_ctx->T ? 1 : 0;
851-
}
852-
853854
// returns either an expression or a thunk
854855
jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr, jl_module_t *inmodule)
855856
{

src/jlfrontend.scm

+34-13
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
error incomplete))
102102
(and (eq? (car e) 'global) (every symbol? (cdr e))))))
103103
(if (eq? e '_)
104-
(syntax-deprecation #f "_ as an rvalue" ""))
104+
(syntax-deprecation "_ as an rvalue" ""))
105105
e)
106106
(else
107107
(let ((last *in-expand*))
@@ -202,18 +202,6 @@
202202
(jl-parse-all (open-input-file filename) filename)
203203
(lambda (e) #f)))
204204

205-
(define *depwarn* #t)
206-
(define (jl-parser-depwarn w)
207-
(let ((prev *depwarn*))
208-
(set! *depwarn* (eq? w #t))
209-
prev))
210-
211-
(define *deperror* #f)
212-
(define (jl-parser-deperror e)
213-
(let ((prev *deperror*))
214-
(set! *deperror* (eq? e #t))
215-
prev))
216-
217205
; expand a piece of raw surface syntax to an executable thunk
218206
(define (jl-expand-to-thunk expr)
219207
(parser-wrap (lambda ()
@@ -229,3 +217,36 @@
229217
(newline)
230218
(prn e))
231219
(lambda () (profile s))))
220+
221+
222+
; --- logging ---
223+
; Utilities for logging messages from the frontend, in a way which can be
224+
; controlled from julia code.
225+
226+
; Log a syntax deprecation from an unknown location
227+
(define (syntax-deprecation what instead)
228+
(syntax-deprecation- what instead 'none 0 #f))
229+
230+
(define (syntax-deprecation- what instead file line exactloc)
231+
(frontend-depwarn (format-syntax-deprecation what instead file line exactloc)
232+
file line))
233+
234+
(define (format-syntax-deprecation what instead file line exactloc)
235+
(string "Deprecated syntax \"" what "\""
236+
(if (or (= line 0) (eq? file 'none))
237+
""
238+
(string (if exactloc " at " " around ") file ":" line))
239+
"."
240+
(if (equal? instead "") ""
241+
(string #\newline "Use \"" instead "\" instead."))))
242+
243+
; Emit deprecation warning via julia logging layer if posible. If not - eg,
244+
; in bootstrap or in the special case that deprecations have been set to
245+
; errors, do the job here.
246+
(define (frontend-depwarn msg file line)
247+
(let ((warnstatus (julia-depwarn msg file line)))
248+
(cond ((eq? warnstatus 2) (error msg))
249+
((eq? warnstatus 1) (io.write *stderr* msg))
250+
; (eq? warnstatus 0) - successfully logged
251+
)))
252+

0 commit comments

Comments
 (0)