diff --git a/j/multi.j b/j/multi.j index 0841ddd41cc6e..8666e22441ee9 100644 --- a/j/multi.j +++ b/j/multi.j @@ -1068,25 +1068,43 @@ let lastp = 1 lastp = 1 end end - if p==myid() - # for local spawn, simulate semantics of copying bindings - if isa(env,Tuple) - env = map(x->(isa(x,Box)?Box(x.contents):x), env) - linfo = ccall(:jl_closure_linfo, Any, (Any,), thunk) - thunk = ccall(:jl_new_closure_internal, Any, (Any, Any), - linfo, env)::Function - end - end spawnat(p, thunk) end end -macro spawn(thk) - :(spawn(()->($thk))) +find_vars(e) = find_vars(e, {}) +function find_vars(e, lst) + if isa(e,Symbol) + if isbound(e) && isgeneric(eval(e)) + # exclude global generic functions + else + push(lst, e) + end + elseif isa(e,Expr) + foreach(x->find_vars(x,lst), e.args) + end + lst +end + +# wrap an expression in "let a=a,b=b,..." for each var it references +function localize_vars(expr) + v = find_vars(expr) + # requires a special feature of the front end that knows how to insert + # the correct variables. the list of free variables cannot be computed + # from a macro. + Expr(:localize, + {:(()->($expr)), v...}, + Any) +end + +macro spawn(expr) + expr = localize_vars(:(()->($expr))) + :(spawn($expr)) end -macro spawnlocal(thk) - :(spawnat(LocalProcess(), ()->($thk))) +macro spawnlocal(expr) + expr = localize_vars(:(()->($expr))) + :(spawnat(LocalProcess(), $expr)) end at_each(f, args...) = at_each(PGRP, f, args...) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index c79096d73885f..13bbdbfb61a0d 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1394,6 +1394,19 @@ So far only the second case can actually occur. `(lambda ,args (vinf ,(caddr e) ,vi ,cv ()) ,bod))) + ((eq? (car e) 'localize) + ;; special feature for @spawn that wraps a piece of code in a "let" + ;; binding each free variable. + (let ((env-vars (map vinfo:name env)) + (localize-vars (cddr e))) + (let ((vs (filter + (lambda (v) (or (memq v localize-vars) + (memq v env-vars))) + (free-vars (cadr e))))) + (analyze-vars + `(call (lambda ,vs ,(caddr (cadr e)) ,(cadddr (cadr e))) + ,@vs) + env)))) (else (cons (car e) (map (lambda (x) (analyze-vars x env)) (cdr e))))))