Skip to content

Commit

Permalink
more precise types in keyword argument method lowering
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Feb 1, 2019
1 parent 0b0a394 commit 1cd1e6c
Showing 1 changed file with 64 additions and 43 deletions.
107 changes: 64 additions & 43 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -434,21 +434,19 @@
(rkw (if (null? restkw) (make-ssavalue) (symbol (string (car restkw) "..."))))
(mangled (symbol (string "#" (if name (undot-name name) 'call) "#"
(string (current-julia-module-counter))))))
`(block
;; this is a hack: nest these statements inside a call so they get closure
;; converted together, allowing all needed types to be defined before any methods.
`(call (core ifelse) false false (block
;; forward-declare function so its type can occur in the signature of the inner method below
,@(if (or (symbol? name) (globalref? name)) `((method ,name)) '())

;; call with keyword args pre-sorted - original method code goes here
,(method-def-expr-
mangled sparams
`((|::| ,mangled (call (core typeof) ,mangled)) ,@vars ,@restkw
;; strip type off function self argument if not needed for a static param.
;; then it is ok for cl-convert to move this definition above the original def.
,(if (decl? (car not-optional))
(if (any (lambda (sp)
(expr-contains-eq (car sp) (caddr (car not-optional))))
positional-sparams)
(car not-optional)
(decl-var (car not-optional)))
(car not-optional))
,@(cdr not-optional) ,@vararg)
,@not-optional ,@vararg)
(insert-after-meta `(block
,@stmts)
annotations)
Expand Down Expand Up @@ -529,7 +527,7 @@
(list `(... ,(arg-name (car vararg)))))))))))
;; return primary function
,(if (not (symbol? name))
'(null) name)))))
'(null) name))))))

;; prologue includes line number node and eventual meta nodes
(define (extract-method-prologue body)
Expand Down Expand Up @@ -2770,7 +2768,7 @@ f(x) = yt(x)

(define (convert-lambda lam fname interp capt-sp)
(let ((body (add-box-inits-to-body
lam (cl-convert (cadddr lam) fname lam (table) #f interp))))
lam (cl-convert (cadddr lam) fname lam (table) (table) #f interp))))
`(lambda ,(lam:args lam)
(,(clear-capture-bits (car (lam:vinfo lam)))
()
Expand Down Expand Up @@ -2833,7 +2831,7 @@ f(x) = yt(x)
(make-ssavalue)))
(rhs (if (equal? vt '(core Any))
rhs1
(convert-for-type-decl rhs1 (cl-convert vt fname lam #f #f interp))))
(convert-for-type-decl rhs1 (cl-convert vt fname lam #f #f #f interp))))
(ex (cond (closed `(call (core setfield!)
,(if interp
`($ ,var)
Expand Down Expand Up @@ -2888,7 +2886,12 @@ f(x) = yt(x)
(cadr e))
e))))
(let ((e2 (lift- e)))
(cons e2 (apply append (reverse top))))))
(let ((stmts (apply append (reverse top))))
;; move all type definitions first
(receive (structs others)
(separate (lambda (x) (and (pair? x) (eq? (car x) 'thunk)))
stmts)
(cons e2 (append structs others)))))))

(define (first-non-meta blk)
(let loop ((xs (cdr blk)))
Expand Down Expand Up @@ -3019,7 +3022,7 @@ f(x) = yt(x)
#t)
((eq? (car e) 'scope-block)
(visit (cadr e)))
((eq? (car e) 'block)
((or (eq? (car e) 'block) (eq? (car e) 'call))
(for-each visit (cdr e)))
((eq? (car e) 'break-block)
(visit (caddr e)))
Expand Down Expand Up @@ -3072,23 +3075,23 @@ f(x) = yt(x)
(define (toplevel-preserving? e)
(and (pair? e) (memq (car e) '(if block trycatch tryfinally))))

(define (map-cl-convert exprs fname lam namemap toplevel interp)
(define (map-cl-convert exprs fname lam namemap defined toplevel interp)
(if toplevel
(map (lambda (x)
(let ((tl (lift-toplevel (cl-convert x fname lam namemap
(let ((tl (lift-toplevel (cl-convert x fname lam namemap defined
(and toplevel (toplevel-preserving? x))
interp))))
(if (null? (cdr tl))
(car tl)
`(block ,@(cdr tl) ,(car tl)))))
exprs)
(map (lambda (x) (cl-convert x fname lam namemap #f interp)) exprs)))
(map (lambda (x) (cl-convert x fname lam namemap defined #f interp)) exprs)))

(define (cl-convert e fname lam namemap toplevel interp)
(define (cl-convert e fname lam namemap defined toplevel interp)
(if (and (not lam)
(not (and (pair? e) (memq (car e) '(lambda method macro)))))
(if (atom? e) e
(cons (car e) (map-cl-convert (cdr e) fname lam namemap toplevel interp)))
(cons (car e) (map-cl-convert (cdr e) fname lam namemap defined toplevel interp)))
(cond
((symbol? e)
(define (new-undef-var name)
Expand All @@ -3107,7 +3110,7 @@ f(x) = yt(x)
(val (if (equal? typ '(core Any))
val
`(call (core typeassert) ,val
,(cl-convert typ fname lam namemap toplevel interp)))))
,(cl-convert typ fname lam namemap defined toplevel interp)))))
`(block
,@(if (eq? box access) '() `((= ,access ,box)))
,undefcheck
Expand All @@ -3134,7 +3137,7 @@ f(x) = yt(x)
((quote top core globalref outerref line break inert module toplevel null meta) e)
((=)
(let ((var (cadr e))
(rhs (cl-convert (caddr e) fname lam namemap toplevel interp)))
(rhs (cl-convert (caddr e) fname lam namemap defined toplevel interp)))
(convert-assignment var rhs fname lam interp)))
((local-def) ;; make new Box for local declaration of defined variable
(let ((vi (assq (cadr e) (car (lam:vinfo lam)))))
Expand Down Expand Up @@ -3183,7 +3186,7 @@ f(x) = yt(x)
(sp-inits (if (or short (not (eq? (car sig) 'block)))
'()
(map-cl-convert (butlast (cdr sig))
fname lam namemap toplevel interp)))
fname lam namemap defined toplevel interp)))
(sig (and sig (if (eq? (car sig) 'block)
(last sig)
sig))))
Expand All @@ -3200,14 +3203,20 @@ f(x) = yt(x)
(list-tail (car (lam:vinfo lam2)) (length (lam:args lam2))))
(lambda-optimize-vars! lam2)))
(if (not local) ;; not a local function; will not be closure converted to a new type
(cond (short e)
(cond (short (if (has? defined (cadr e))
'(null)
`(toplevel-butfirst
;; wrap in toplevel-butfirst so it gets moved higher along with
;; closure type definitions
,e
(thunk (lambda () (() () 0 ()) (block (return ,e)))))))
((null? cvs)
`(block
,@sp-inits
(method ,name ,(cl-convert sig fname lam namemap toplevel interp)
(method ,name ,(cl-convert sig fname lam namemap defined toplevel interp)
,(let ((body (add-box-inits-to-body
lam2
(cl-convert (cadddr lam2) 'anon lam2 (table) #f interp))))
(cl-convert (cadddr lam2) 'anon lam2 (table) (table) #f interp))))
`(lambda ,(cadr lam2)
(,(clear-capture-bits (car vis))
,@(cdr vis))
Expand All @@ -3218,13 +3227,13 @@ f(x) = yt(x)
(newlam (compact-and-renumber (linearize (car exprs)) 'none 0)))
`(toplevel-butfirst
(block ,@sp-inits
(method ,name ,(cl-convert sig fname lam namemap toplevel interp)
(method ,name ,(cl-convert sig fname lam namemap defined toplevel interp)
,(julia-bq-macro newlam)))
,@top-stmts))))

;; local case - lift to a new type at top level
(let* ((exists (get namemap name #f))
(type-name (or exists
(let* ((exists (get defined name #f))
(type-name (or (get namemap name #f)
(and name
(symbol (string "#" name "#" (current-julia-module-counter))))))
(alldefs (expr-find-all
Expand All @@ -3233,8 +3242,12 @@ f(x) = yt(x)
(eq? (method-expr-name ex) name)))
(lam:body lam)
identity
(lambda (x) (and (pair? x) (not (eq? (car x) 'lambda))))))
(all-capt-vars (delete-duplicates
(lambda (x) (and (pair? x) (not (eq? (car x) 'lambda)))))))
(and name (put! namemap name type-name))
(if (and short (pair? alldefs))
;; for (method f) do nothing unless it's the only definition of f
'(null)
(let* ((all-capt-vars (delete-duplicates
(apply append ;; merge captured vars from all definitions
cvs
(map (lambda (methdef)
Expand Down Expand Up @@ -3270,8 +3283,10 @@ f(x) = yt(x)
(memq (car e) '(= method))
(eq? (cadr e) s)))
(caddr e))))
(error (string "local variable " s
" cannot be used in closure declaration"))
(if (has? namemap s)
#f
(error (string "local variable " s
" cannot be used in closure declaration")))
#t)
#f)))
(caddr e)
Expand Down Expand Up @@ -3315,7 +3330,7 @@ f(x) = yt(x)
(append (map (lambda (gs tvar)
(make-assignment gs `(call (core TypeVar) ',tvar (core Any))))
closure-param-syms closure-param-names)
`((method #f ,(cl-convert arg-defs fname lam namemap toplevel interp)
`((method #f ,(cl-convert arg-defs fname lam namemap defined toplevel interp)
,(convert-lambda lam2
(if iskw
(caddr (lam:args lam2))
Expand Down Expand Up @@ -3346,23 +3361,24 @@ f(x) = yt(x)
(filter (lambda (vi)
(not (memq (car vi) moved-vars)))
(car (lam:vinfo lam)))))
(put! defined name #t)
`(toplevel-butfirst
,(if exists
'(null)
(convert-assignment name mk-closure fname lam interp))
,@(if exists
'()
(begin (and name (put! namemap name type-name))
typedef))
typedef)
,@(map (lambda (v) `(moved-local ,v)) moved-vars)
,@sp-inits
,@mk-method)))))
,@mk-method)))))))
((lambda) ;; happens inside (thunk ...) and generated function bodies
(for-each (lambda (vi) (vinfo:set-asgn! vi #t))
(list-tail (car (lam:vinfo e)) (length (lam:args e))))
(let ((body (map-cl-convert (cdr (lam:body e)) 'anon
(lambda-optimize-vars! e)
(table)
(table)
(null? (cadr e)) ;; only toplevel thunks have 0 args
interp)))
`(lambda ,(cadr e)
Expand All @@ -3371,7 +3387,7 @@ f(x) = yt(x)
(block ,@body))))
;; remaining `::` expressions are type assertions
((|::|)
(cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap toplevel interp))
(cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap defined toplevel interp))
;; remaining `decl` expressions are only type assertions if the
;; argument is global or a non-symbol.
((decl)
Expand All @@ -3381,14 +3397,19 @@ f(x) = yt(x)
(else
(if (or (symbol? (cadr e)) (and (pair? (cadr e)) (eq? (caadr e) 'outerref)))
(error "type declarations on global variables are not yet supported"))
(cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap toplevel interp))))
(cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap defined toplevel interp))))
;; `with-static-parameters` expressions can be removed now; used only by analyze-vars
((with-static-parameters)
(cl-convert (cadr e) fname lam namemap toplevel interp))
(else (cons (car e)
(map-cl-convert (cdr e) fname lam namemap toplevel interp))))))))

(define (closure-convert e) (cl-convert e #f #f #f #f #f))
(cl-convert (cadr e) fname lam namemap defined toplevel interp))
(else
(if (eq? (car e) 'struct_type)
;; struct_type has the effect of defining a name, so we don't try to
;; emit a defining (method x) expr.
(put! defined (cadr e) #t))
(cons (car e)
(map-cl-convert (cdr e) fname lam namemap defined toplevel interp))))))))

(define (closure-convert e) (cl-convert e #f #f #f #f #f #f))

;; pass 5: convert to linear IR

Expand Down

0 comments on commit 1cd1e6c

Please sign in to comment.