From e2d54013fe83d3f62786be03aee3267d29aa6eea Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 2 Mar 2018 17:13:48 -0500 Subject: [PATCH] lower top-level statements in such a way that the front-end knows their values are not used fixes most false positives in the deprecation for using the value of `.=` --- src/ast.c | 21 +++++++++++++++++++-- src/jlfrontend.scm | 17 ++++++++++++----- src/julia.h | 1 + src/julia_internal.h | 2 +- src/toplevel.c | 2 +- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/ast.c b/src/ast.c index d6c8968350187d..a3dc018e05e301 100644 --- a/src/ast.c +++ b/src/ast.c @@ -61,7 +61,7 @@ jl_sym_t *generated_only_sym; jl_sym_t *isdefined_sym; jl_sym_t *nospecialize_sym; jl_sym_t *macrocall_sym; jl_sym_t *colon_sym; jl_sym_t *hygienicscope_sym; -jl_sym_t *escape_sym; +jl_sym_t *escape_sym; jl_sym_t *block_sym; jl_sym_t *gc_preserve_begin_sym; jl_sym_t *gc_preserve_end_sym; jl_sym_t *throw_undef_if_not_sym; @@ -385,6 +385,7 @@ void jl_init_frontend(void) generated_sym = jl_symbol("generated"); generated_only_sym = jl_symbol("generated_only"); throw_undef_if_not_sym = jl_symbol("throw_undef_if_not"); + block_sym = jl_symbol("block"); } JL_DLLEXPORT void jl_lisp_prompt(void) @@ -829,7 +830,11 @@ jl_value_t *jl_parse_eval_all(const char *fname, form = jl_expand_macros(form, inmodule, NULL, 0); expression = julia_to_scm(fl_ctx, form); } - expression = fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, "jl-expand-to-thunk")), expression); + // expand non-final expressions in statement position (value unused) + expression = + fl_applyn(fl_ctx, 1, + symbol_value(symbol(fl_ctx, iscons(cdr_(ast)) ? "jl-expand-to-thunk-stmt" : "jl-expand-to-thunk")), + expression); } jl_get_ptls_states()->world_age = jl_world_counter; form = scm_to_julia(fl_ctx, expression, inmodule); @@ -1115,6 +1120,18 @@ JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr, jl_module_t *inmodule) return expr; } +// expand in a context where the expression value is unused +JL_DLLEXPORT jl_value_t *jl_expand_stmt(jl_value_t *expr, jl_module_t *inmodule) +{ + JL_TIMING(LOWERING); + JL_GC_PUSH1(&expr); + expr = jl_copy_ast(expr); + expr = jl_expand_macros(expr, inmodule, NULL, 0); + expr = jl_call_scm_on_ast("jl-expand-to-thunk-stmt", expr, inmodule); + JL_GC_POP(); + return expr; +} + #ifdef __cplusplus } diff --git a/src/jlfrontend.scm b/src/jlfrontend.scm index 8dc9a853f50142..9572225af114b8 100644 --- a/src/jlfrontend.scm +++ b/src/jlfrontend.scm @@ -94,12 +94,14 @@ (define *in-expand* #f) +(define (toplevel-only-expr? e) + (and (pair? e) + (or (memq (car e) '(toplevel line module import importall using export + error incomplete)) + (and (eq? (car e) 'global) (every symbol? (cdr e)))))) + (define (expand-toplevel-expr e) - (cond ((or (atom? e) - (and (pair? e) - (or (memq (car e) '(toplevel line module import importall using export - error incomplete)) - (and (eq? (car e) 'global) (every symbol? (cdr e)))))) + (cond ((or (atom? e) (toplevel-only-expr? e)) (if (underscore-symbol? e) (syntax-deprecation "underscores as an rvalue" "" #f)) e) @@ -207,6 +209,11 @@ (parser-wrap (lambda () (expand-toplevel-expr expr)))) +(define (jl-expand-to-thunk-stmt expr) + (jl-expand-to-thunk (if (toplevel-only-expr? expr) + expr + `(block ,expr (null))))) + ; run whole frontend on a string. useful for testing. (define (fe str) (expand-toplevel-expr (julia-parse str))) diff --git a/src/julia.h b/src/julia.h index de449173e0100f..9b11afdfffd80a 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1450,6 +1450,7 @@ JL_DLLEXPORT jl_value_t *jl_parse_string(const char *str, size_t len, JL_DLLEXPORT jl_value_t *jl_load_file_string(const char *text, size_t len, char *filename, jl_module_t *inmodule); JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr, jl_module_t *inmodule); +JL_DLLEXPORT jl_value_t *jl_expand_stmt(jl_value_t *expr, jl_module_t *inmodule); JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str); // external libraries diff --git a/src/julia_internal.h b/src/julia_internal.h index ec4de625ddb16d..5df73f0a5b505a 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1015,7 +1015,7 @@ extern jl_sym_t *compiler_temp_sym; extern jl_sym_t *foreigncall_sym; extern jl_sym_t *const_sym; extern jl_sym_t *thunk_sym; extern jl_sym_t *underscore_sym; extern jl_sym_t *colon_sym; extern jl_sym_t *abstracttype_sym; extern jl_sym_t *primtype_sym; -extern jl_sym_t *structtype_sym; +extern jl_sym_t *structtype_sym; extern jl_sym_t *block_sym; extern jl_sym_t *global_sym; extern jl_sym_t *unused_sym; extern jl_sym_t *boundscheck_sym; extern jl_sym_t *inbounds_sym; extern jl_sym_t *copyast_sym; extern jl_sym_t *fastmath_sym; diff --git a/src/toplevel.c b/src/toplevel.c index c3279117dacbef..c8f27868f3ed4b 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -228,7 +228,7 @@ jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex) for (int i = 0; i < jl_array_len(exprs); i++) { // process toplevel form ptls->world_age = jl_world_counter; - form = jl_expand(jl_array_ptr_ref(exprs, i), newm); + form = jl_expand_stmt(jl_array_ptr_ref(exprs, i), newm); ptls->world_age = jl_world_counter; (void)jl_toplevel_eval_flex(newm, form, 1, 1); }