19651965 ,@(if (length= e 3) '(()) '())
19661966 ,@(map expand-forms (cddr e))))
19671967
1968+ 'opaque_closure
1969+ (lambda (e)
1970+ (let* ((meth (caddr (caddr (expand-forms (cadr e))))) ;; `method` expr
1971+ (lam (cadddr meth))
1972+ (sig-block (caddr meth))
1973+ (sig-block (if (and (pair? sig-block) (eq? (car sig-block) 'block))
1974+ sig-block
1975+ `(block ,sig-block)))
1976+ (stmts (cdr (butlast sig-block)))
1977+ (sig-svec (last sig-block))
1978+ (typ-svec (caddr sig-svec))
1979+ (tvars (cddr (cadddr sig-svec)))
1980+ (argtypes (cdddr typ-svec))
1981+ (argtype (foldl (lambda (var ex) `(call (core UnionAll) ,var ,ex))
1982+ (expand-forms `(curly (core Tuple) ,@argtypes ))
1983+ (reverse tvars))))
1984+ `(opaque_closure ,argtype ,lam)))
1985+
19681986 'block
19691987 (lambda (e)
19701988 (cond ((null? (cdr e)) '(null))
@@ -3049,9 +3067,9 @@ f(x) = yt(x)
30493067(define (clear-capture-bits vinfos)
30503068 (map vinfo: not-capt vinfos))
30513069
3052- (define (convert-lambda lam fname interp capt-sp)
3070+ (define (convert-lambda lam fname interp capt-sp opaq )
30533071 (let ((body (add-box-inits-to-body
3054- lam (cl-convert (cadddr lam) fname lam (table) (table) #f interp))))
3072+ lam (cl-convert (cadddr lam) fname lam (table) (table) #f interp opaq ))))
30553073 `(lambda ,(lam: args lam)
30563074 (,(clear-capture-bits (car (lam: vinfo lam)))
30573075 ()
@@ -3091,12 +3109,17 @@ f(x) = yt(x)
30913109 `(block (= ,temp ,(renumber-assigned-ssavalues t)) ,ex)
30923110 ex))))
30933111
3112+ (define (capt-var-access var fname opaq)
3113+ (if opaq
3114+ `(call (core getfield) ,fname ,(get opaq var))
3115+ `(call (core getfield) ,fname (inert ,var))))
3116+
30943117;; convert assignment to a closed variable to a setfield! call.
30953118;; while we're at it, generate `convert` calls for variables with
30963119;; declared types.
30973120;; when doing this, the original value needs to be preserved, to
30983121;; ensure the expression `a=b` always returns exactly `b`.
3099- (define (convert-assignment var rhs0 fname lam interp)
3122+ (define (convert-assignment var rhs0 fname lam interp opaq )
31003123 (cond
31013124 ((symbol? var)
31023125 (let* ((vi (assq var (car (lam: vinfo lam))))
@@ -3114,11 +3137,11 @@ f(x) = yt(x)
31143137 (make-ssavalue)))
31153138 (rhs (if (equal? vt '(core Any))
31163139 rhs1
3117- (convert-for-type-decl rhs1 (cl-convert vt fname lam #f #f #f interp))))
3140+ (convert-for-type-decl rhs1 (cl-convert vt fname lam #f #f #f interp opaq ))))
31183141 (ex (cond (closed `(call (core setfield!)
31193142 ,(if interp
31203143 `($ ,var)
3121- `(call (core getfield) , fname (inert ,var) ))
3144+ (capt-var-access var fname opaq ))
31223145 (inert contents)
31233146 ,rhs))
31243147 (capt `(call (core setfield!) ,var (inert contents) ,rhs))
@@ -3391,23 +3414,30 @@ f(x) = yt(x)
33913414(define (toplevel-preserving? e)
33923415 (and (pair? e) (memq (car e) '(if elseif block trycatch tryfinally))))
33933416
3394- (define (map-cl-convert exprs fname lam namemap defined toplevel interp)
3417+ (define (map-cl-convert exprs fname lam namemap defined toplevel interp opaq )
33953418 (if toplevel
33963419 (map (lambda (x)
33973420 (let ((tl (lift-toplevel (cl-convert x fname lam namemap defined
33983421 (and toplevel (toplevel-preserving? x))
3399- interp))))
3422+ interp opaq ))))
34003423 (if (null? (cdr tl))
34013424 (car tl)
34023425 `(block ,@(cdr tl) ,(car tl)))))
34033426 exprs)
3404- (map (lambda (x) (cl-convert x fname lam namemap defined #f interp)) exprs)))
3427+ (map (lambda (x) (cl-convert x fname lam namemap defined #f interp opaq)) exprs)))
3428+
3429+ (define (prepare-lam lam)
3430+ ;; mark all non-arguments as assigned, since locals that are never assigned
3431+ ;; need to be handled the same as those that are (i.e., boxed).
3432+ (for-each (lambda (vi) (vinfo: set-asgn! vi #t))
3433+ (list-tail (car (lam: vinfo lam)) (length (lam: args lam))))
3434+ (lambda-optimize-vars! lam))
34053435
3406- (define (cl-convert e fname lam namemap defined toplevel interp)
3436+ (define (cl-convert e fname lam namemap defined toplevel interp opaq )
34073437 (if (and (not lam)
3408- (not (and (pair? e) (memq (car e) '(lambda method macro)))))
3438+ (not (and (pair? e) (memq (car e) '(lambda method macro opaque_closure )))))
34093439 (if (atom? e) e
3410- (cons (car e) (map-cl-convert (cdr e) fname lam namemap defined toplevel interp)))
3440+ (cons (car e) (map-cl-convert (cdr e) fname lam namemap defined toplevel interp opaq )))
34113441 (cond
34123442 ((symbol? e)
34133443 (define (new-undef-var name)
@@ -3426,7 +3456,7 @@ f(x) = yt(x)
34263456 (val (if (equal? typ '(core Any))
34273457 val
34283458 `(call (core typeassert) ,val
3429- ,(cl-convert typ fname lam namemap defined toplevel interp)))))
3459+ ,(cl-convert typ fname lam namemap defined toplevel interp opaq )))))
34303460 `(block
34313461 ,@(if (eq? box access) '() `((= ,access ,box)))
34323462 ,undefcheck
@@ -3438,7 +3468,7 @@ f(x) = yt(x)
34383468 (cv
34393469 (let ((access (if interp
34403470 `($ (call (core QuoteNode) ,e))
3441- `(call (core getfield) , fname (inert ,e) ))))
3471+ (capt-var-access e fname opaq ))))
34423472 (if (and (vinfo: asgn cv) (vinfo: capt cv))
34433473 (get-box-contents access (vinfo: type cv))
34443474 access)))
@@ -3458,8 +3488,8 @@ f(x) = yt(x)
34583488 e)
34593489 ((=)
34603490 (let ((var (cadr e))
3461- (rhs (cl-convert (caddr e) fname lam namemap defined toplevel interp)))
3462- (convert-assignment var rhs fname lam interp)))
3491+ (rhs (cl-convert (caddr e) fname lam namemap defined toplevel interp opaq )))
3492+ (convert-assignment var rhs fname lam interp opaq )))
34633493 ((local-def) ;; make new Box for local declaration of defined variable
34643494 (let ((vi (assq (cadr e) (car (lam: vinfo lam)))))
34653495 (if (and vi (vinfo: asgn vi) (vinfo: capt vi))
@@ -3487,14 +3517,28 @@ f(x) = yt(x)
34873517 (if (and (vinfo: asgn cv) (vinfo: capt cv))
34883518 (let ((access (if interp
34893519 `($ (call (core QuoteNode) ,sym))
3490- `(call (core getfield) , fname (inert ,sym) ))))
3520+ (capt-var-access sym fname opaq ))))
34913521 `(call (core isdefined) ,access (inert contents)))
34923522 '(true)))
34933523 (vi
34943524 (if (and (vinfo: asgn vi) (vinfo: capt vi))
34953525 `(call (core isdefined) ,sym (inert contents))
34963526 e))
34973527 (else e))))
3528+ ((opaque_closure)
3529+ (let* ((lam2 (caddr e))
3530+ (vis (lam: vinfo lam2))
3531+ (cvs (map car (cadr vis))))
3532+ (prepare-lam lam2)
3533+ (let ((var-exprs (map (lambda (v)
3534+ (let ((cv (assq v (cadr (lam: vinfo lam)))))
3535+ (if cv
3536+ (capt-var-access v fname opaq)
3537+ v)))
3538+ cvs)))
3539+ `(call (core _opaque_closure) ,(cadr e) (call (core apply_type) Union) (core Any)
3540+ (anonymous_closure ,(convert-lambda lam2 (car (lam: args lam2)) #f '() (symbol-to-idx-map cvs)))
3541+ ,@var -exprs))))
34983542 ((method)
34993543 (let* ((name (method-expr-name e))
35003544 (short (length= e 2)) ;; function f end
@@ -3507,7 +3551,7 @@ f(x) = yt(x)
35073551 (sp-inits (if (or short (not (eq? (car sig) 'block)))
35083552 '()
35093553 (map-cl-convert (butlast (cdr sig))
3510- fname lam namemap defined toplevel interp)))
3554+ fname lam namemap defined toplevel interp opaq )))
35113555 (sig (and sig (if (eq? (car sig) 'block)
35123556 (last sig)
35133557 sig))))
@@ -3516,13 +3560,7 @@ f(x) = yt(x)
35163560 (error (string "cannot add method to function argument " name)))
35173561 (if (eqv? (string.char (string name) 0) #\@)
35183562 (error "macro definition not allowed inside a local scope"))))
3519- (if lam2
3520- (begin
3521- ;; mark all non-arguments as assigned, since locals that are never assigned
3522- ;; need to be handled the same as those that are (i.e., boxed).
3523- (for-each (lambda (vi) (vinfo: set-asgn! vi #t))
3524- (list-tail (car (lam: vinfo lam2)) (length (lam: args lam2))))
3525- (lambda-optimize-vars! lam2)))
3563+ (if lam2 (prepare-lam lam2))
35263564 (if (not local) ;; not a local function; will not be closure converted to a new type
35273565 (cond (short (if (has? defined (cadr e))
35283566 e
@@ -3540,21 +3578,21 @@ f(x) = yt(x)
35403578 ;; anonymous functions with keyword args generate global
35413579 ;; functions that refer to the type of a local function
35423580 (rename-sig-types sig namemap)
3543- fname lam namemap defined toplevel interp)
3581+ fname lam namemap defined toplevel interp opaq )
35443582 ,(let ((body (add-box-inits-to-body
35453583 lam2
3546- (cl-convert (cadddr lam2) 'anon lam2 (table) (table) #f interp))))
3584+ (cl-convert (cadddr lam2) 'anon lam2 (table) (table) #f interp opaq ))))
35473585 `(lambda ,(cadr lam2)
35483586 (,(clear-capture-bits (car vis))
35493587 ,@(cdr vis))
35503588 ,body)))))
35513589 (else
3552- (let* ((exprs (lift-toplevel (convert-lambda lam2 '|#anon| #t '())))
3590+ (let* ((exprs (lift-toplevel (convert-lambda lam2 '|#anon| #t '() #f )))
35533591 (top-stmts (cdr exprs))
35543592 (newlam (compact-and-renumber (linearize (car exprs)) 'none 0)))
35553593 `(toplevel-butfirst
35563594 (block ,@sp -inits
3557- (method ,name ,(cl-convert sig fname lam namemap defined toplevel interp)
3595+ (method ,name ,(cl-convert sig fname lam namemap defined toplevel interp opaq )
35583596 ,(julia-bq-macro newlam)))
35593597 ,@top -stmts))))
35603598
@@ -3657,19 +3695,19 @@ f(x) = yt(x)
36573695 (append (map (lambda (gs tvar)
36583696 (make-assignment gs `(call (core TypeVar) ',tvar (core Any))))
36593697 closure-param-syms closure-param-names)
3660- `((method #f ,(cl-convert arg-defs fname lam namemap defined toplevel interp)
3698+ `((method #f ,(cl-convert arg-defs fname lam namemap defined toplevel interp opaq )
36613699 ,(convert-lambda lam2
36623700 (if iskw
36633701 (caddr (lam: args lam2))
36643702 (car (lam: args lam2)))
3665- #f closure-param-names)))))))
3703+ #f closure-param-names #f )))))))
36663704 (mk-closure ;; expression to make the closure
36673705 (let* ((var-exprs (map (lambda (v)
36683706 (let ((cv (assq v (cadr (lam: vinfo lam)))))
36693707 (if cv
36703708 (if interp
36713709 `($ (call (core QuoteNode) ,v))
3672- `(call (core getfield) , fname (inert ,v) ))
3710+ (capt-var-access v fname opaq ))
36733711 v)))
36743712 capt-vars))
36753713 (P (append
@@ -3696,7 +3734,7 @@ f(x) = yt(x)
36963734 (begin
36973735 (put! defined name #t)
36983736 `(toplevel-butfirst
3699- ,(convert-assignment name mk-closure fname lam interp)
3737+ ,(convert-assignment name mk-closure fname lam interp opaq )
37003738 ,@typedef
37013739 ,@(map (lambda (v) `(moved-local ,v)) moved-vars)
37023740 ,@sp -inits
@@ -3709,14 +3747,14 @@ f(x) = yt(x)
37093747 (table)
37103748 (table)
37113749 (null? (cadr e)) ;; only toplevel thunks have 0 args
3712- interp)))
3750+ interp opaq )))
37133751 `(lambda ,(cadr e)
37143752 (,(clear-capture-bits (car (lam: vinfo e)))
37153753 () ,@(cddr (lam: vinfo e)))
37163754 (block ,@body ))))
37173755 ;; remaining `::` expressions are type assertions
37183756 ((|::|)
3719- (cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap defined toplevel interp))
3757+ (cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap defined toplevel interp opaq ))
37203758 ;; remaining `decl` expressions are only type assertions if the
37213759 ;; argument is global or a non-symbol.
37223760 ((decl)
@@ -3726,15 +3764,15 @@ f(x) = yt(x)
37263764 (else
37273765 (if (or (symbol? (cadr e)) (and (pair? (cadr e)) (eq? (caadr e) 'outerref)))
37283766 (error "type declarations on global variables are not yet supported"))
3729- (cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap defined toplevel interp))))
3767+ (cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap defined toplevel interp opaq ))))
37303768 ;; `with-static-parameters` expressions can be removed now; used only by analyze-vars
37313769 ((with-static-parameters)
3732- (cl-convert (cadr e) fname lam namemap defined toplevel interp))
3770+ (cl-convert (cadr e) fname lam namemap defined toplevel interp opaq ))
37333771 (else
37343772 (cons (car e)
3735- (map-cl-convert (cdr e) fname lam namemap defined toplevel interp))))))))
3773+ (map-cl-convert (cdr e) fname lam namemap defined toplevel interp opaq ))))))))
37363774
3737- (define (closure-convert e) (cl-convert e #f #f #f #f #f #f))
3775+ (define (closure-convert e) (cl-convert e #f #f #f #f #f #f #f ))
37383776
37393777;; pass 5: convert to linear IR
37403778
@@ -4250,6 +4288,11 @@ f(x) = yt(x)
42504288 (cond (tail (emit-return temp))
42514289 (value temp)
42524290 (else (emit temp)))))
4291+ ((anonymous_closure)
4292+ (let ((temp `(anonymous_closure ,(linearize (cadr e)))))
4293+ (cond (tail (emit-return temp))
4294+ (value temp)
4295+ (else (emit temp)))))
42534296
42544297 ;; top level expressions
42554298 ((thunk module)
@@ -4473,14 +4516,6 @@ f(x) = yt(x)
44734516 (loop (cdr stmts)))))
44744517 (vector (reverse code) (reverse locs) (reverse linetable) ssavtable labltable)))
44754518
4476- (define (symbol-to-idx-map lst)
4477- (let ((tbl (table)))
4478- (let loop ((xs lst) (i 1))
4479- (if (pair? xs)
4480- (begin (put! tbl (car xs) i)
4481- (loop (cdr xs) (+ i 1)))))
4482- tbl))
4483-
44844519(define (renumber-lambda lam file line)
44854520 (let* ((stuff (compact-ir (lam: body lam) file line))
44864521 (code (aref stuff 0))
0 commit comments