diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 4aeec39a5eb0c7..272dff96c10d0b 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -9,11 +9,11 @@ transpose(F::Factorization) = error("transpose not implemented for $(typeof(F))" ctranspose(F::Factorization) = error("ctranspose not implemented for $(typeof(F))") macro assertposdef(A, info) - :(($info)==0 ? $A : throw(PosDefException($info))) + :($(esc(info)) == 0 ? $(esc(A)) : throw(PosDefException($(esc(info))))) end macro assertnonsingular(A, info) - :(($info)==0 ? $A : throw(SingularException($info))) + :($(esc(info)) == 0 ? $(esc(A)) : throw(SingularException($(esc(info))))) end diff --git a/base/sparse/cholmod_h.jl b/base/sparse/cholmod_h.jl index 5f51ec50463ea2..922b3b772b7cc3 100644 --- a/base/sparse/cholmod_h.jl +++ b/base/sparse/cholmod_h.jl @@ -75,5 +75,5 @@ type CHOLMODException <: Exception end macro isok(A) - :($A == TRUE || throw(CHOLMODException(""))) + :($(esc(A)) == TRUE || throw(CHOLMODException(""))) end diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index 3b426bb9f234d2..cdfc68b50a08e0 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -54,7 +54,7 @@ function umferror(status::Integer) end macro isok(A) - :(umferror($A)) + :(umferror($(esc(A)))) end # check the size of SuiteSparse_long diff --git a/src/ast.c b/src/ast.c index 3a97b4b975cbfc..9f66cc338056ce 100644 --- a/src/ast.c +++ b/src/ast.c @@ -172,14 +172,14 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg fl_gc_handle(fl_ctx, &scm); value_t scmresult; jl_module_t *defmod = mfunc->def->module; - if (defmod == NULL || defmod == jl_current_module) { - scmresult = fl_cons(fl_ctx, scm, fl_ctx->F); - } - else { - value_t opaque = cvalue(fl_ctx, jl_ast_ctx(fl_ctx)->jvtype, sizeof(void*)); - *(jl_value_t**)cv_data((cvalue_t*)ptr(opaque)) = (jl_value_t*)defmod; - scmresult = fl_cons(fl_ctx, scm, opaque); - } + /* if (defmod == NULL || defmod == jl_current_module) { */ + /* scmresult = fl_cons(fl_ctx, scm, fl_ctx->F); */ + /* } */ + /* else { */ + value_t opaque = cvalue(fl_ctx, jl_ast_ctx(fl_ctx)->jvtype, sizeof(void*)); + *(jl_value_t**)cv_data((cvalue_t*)ptr(opaque)) = (jl_value_t*)defmod; + scmresult = fl_cons(fl_ctx, scm, opaque); + /* } */ fl_free_gc_handles(fl_ctx, 1); JL_GC_POP(); @@ -667,6 +667,19 @@ static value_t julia_to_scm_(fl_context_t *fl_ctx, jl_value_t *v) return julia_to_list2(fl_ctx, (jl_value_t*)inert_sym, jl_fieldref(v,0)); if (jl_typeis(v, jl_newvarnode_type)) return julia_to_list2(fl_ctx, (jl_value_t*)newvar_sym, jl_fieldref(v,0)); + if (jl_typeis(v, jl_globalref_type)) { + jl_module_t *m = jl_globalref_mod(v); + jl_sym_t *sym = jl_globalref_name(v); + if (m == jl_core_module) + return julia_to_list2(fl_ctx, (jl_value_t*)core_sym, + (jl_value_t*)sym); + value_t args = julia_to_list2(fl_ctx, (jl_value_t*)m, (jl_value_t*)sym); + fl_gc_handle(fl_ctx, &args); + value_t hd = julia_to_scm_(fl_ctx, (jl_value_t*)globalref_sym); + value_t scmv = fl_cons(fl_ctx, hd, args); + fl_free_gc_handles(fl_ctx, 1); + return scmv; + } if (jl_is_long(v) && fits_fixnum(jl_unbox_long(v))) return fixnum(jl_unbox_long(v)); if (jl_is_ssavalue(v)) diff --git a/src/builtins.c b/src/builtins.c index 60a323ac09b812..7a1f9515d8a137 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -676,8 +676,17 @@ JL_CALLABLE(jl_f_setfield) JL_NARGS(setfield!, 3, 3); jl_value_t *v = args[0]; jl_value_t *vt = (jl_value_t*)jl_typeof(v); - if (vt == (jl_value_t*)jl_module_type) - jl_error("cannot assign variables in other modules"); + if (vt == (jl_value_t*)jl_module_type) { + jl_module_t *m = (jl_module_t*)v; + jl_sym_t *sym = (jl_sym_t*)args[1]; + if (!jl_is_symbol(sym)) + jl_type_error("setfield!", (jl_value_t*)jl_symbol_type, args[1]); + jl_binding_t *b = jl_get_binding_wr(m, sym); + if (b == NULL) + jl_undefined_var_error(sym); + jl_checked_assignment(b, args[2]); + return args[2]; + } if (!jl_is_datatype(vt)) jl_type_error("setfield!", (jl_value_t*)jl_datatype_type, v); jl_datatype_t *st = (jl_datatype_t*)vt; diff --git a/src/interpreter.c b/src/interpreter.c index 32a087e6033b93..53286a5e988311 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -235,17 +235,28 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, jl_lambda_info_t *la } else if (ex->head == method_sym) { jl_sym_t *fname = (jl_sym_t*)args[0]; - assert(jl_expr_nargs(ex) != 1 || jl_is_symbol(fname)); + assert(jl_expr_nargs(ex) != 1 || jl_is_symbol(fname) || + jl_is_globalref(fname)); - if (jl_is_symbol(fname)) { - jl_value_t **bp=NULL; - jl_value_t *bp_owner=NULL; - jl_binding_t *b=NULL; - if (bp == NULL) { - b = jl_get_binding_for_method_def(jl_current_module, fname); - bp = &b->value; - bp_owner = (jl_value_t*)jl_current_module; - } + if (jl_is_globalref(fname)) { + // allow defining a function using a existing owning binding + // in order for the following code, which may be the result of + // macro expansion, to work. + // + // global f + // M.f() = ... + jl_module_t *m = (jl_module_t*)jl_data_ptr(fname)[0]; + jl_sym_t *sym = (jl_sym_t*)jl_data_ptr(fname)[1]; + assert(jl_is_symbol(sym)); + jl_binding_t *b = jl_get_binding_for_method_def(m, sym); + jl_value_t *gf = jl_generic_function_def(sym, &b->value, + (jl_value_t*)m, b); + if (jl_expr_nargs(ex) == 1) + return gf; + } else if (jl_is_symbol(fname)) { + jl_binding_t *b = jl_get_binding_for_method_def(jl_current_module, fname); + jl_value_t **bp = &b->value; + jl_value_t *bp_owner = (jl_value_t*)jl_current_module; jl_value_t *gf = jl_generic_function_def(fname, bp, bp_owner, b); if (jl_expr_nargs(ex) == 1) return gf; diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 4bc954cfe2b791..07da3b2518f570 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1607,6 +1607,16 @@ (error (string "invalid assignment location \"" (deparse lhs) "\""))) (else (case (car lhs) + ((globalref) + ;; M.b = + (let* ((a (cadr lhs)) + (b (caddr lhs)) + (rhs (caddr e)) + (rr (if (or (symbol-like? rhs) (atom? rhs)) rhs (make-ssavalue)))) + `(block + ,.(if (eq? rr rhs) '() `((= ,rr ,(expand-forms rhs)))) + (call (core setfield!) ,a (quote ,b) ,rr) + (unnecessary ,rr)))) ((|.|) ;; a.b = (let* ((a (cadr lhs)) diff --git a/src/macroexpand.scm b/src/macroexpand.scm index ccf53c82e9efc9..9e2ad5ad02ca1f 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -423,7 +423,7 @@ (error (cadr form))) (let ((form (car form)) (m (cdr form))) - ;; m is the macro's def module, or #f if def env === use env + ;; m is the macro's def module (rename-symbolic-labels (julia-expand-macros (resolve-expansion-vars form m)))))) diff --git a/test/core.jl b/test/core.jl index baa4bbdd63be9b..7229c04cf630bd 100644 --- a/test/core.jl +++ b/test/core.jl @@ -3398,7 +3398,7 @@ end # issue 13855 macro m13855() - Expr(:localize, :(() -> x)) + Expr(:localize, :(() -> $(esc(:x)))) end @noinline function foo13855(x) @m13855() @@ -4203,3 +4203,30 @@ end g1090{T}(x::T)::T = x+1.0 @test g1090(1) === 2 @test g1090(Float32(3)) === Float32(4) + +module TestModuleAssignment +using Base.Test +@eval $(GlobalRef(TestModuleAssignment, :x)) = 1 +@test x == 1 +@eval $(GlobalRef(TestModuleAssignment, :x)) = 2 +@test x == 2 +end + +# issue #14893 +module M14893 +x = 14893 +macro m14893() + :x +end +function f14893() + x = 1 + @m14893 +end +end +function f14893() + x = 2 + M14893.@m14893 +end + +@test f14893() == 14893 +@test M14893.f14893() == 14893