Skip to content

Commit

Permalink
partial fix for loop fusion and splatting (but only handles args... i…
Browse files Browse the repository at this point in the history
…f they are the last argument in the fusion)
  • Loading branch information
stevengj committed Jul 12, 2016
1 parent 47f5e8a commit 0c4b67e
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 13 deletions.
27 changes: 14 additions & 13 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1554,17 +1554,22 @@
(define (fuse? e) (and (pair? e) (eq? (car e) 'fuse)))
(define (anyfuse? exprs)
(if (null? exprs) #f (if (fuse? (car exprs)) #t (anyfuse? (cdr exprs)))))
(define (...? e) (and (pair? e) (eq? (car e) '...)))
(define (to-lambda f args) ; convert f to anonymous function with hygienic tuple args
(define (genarg arg) (if (...? arg) (list '... (gensy)) (gensy)))
(define (hygienic f) ; rename args of f == (-> (tuple args...) body)
(let* ((oldargs (cdadr f))
(newargs (map (lambda (arg) (gensy)) oldargs))
(renames (map cons oldargs newargs)))
(newargs (map genarg oldargs))
(renames (map (lambda (oldarg newarg) (if (...? oldarg)
(cons (cadr oldarg) (cadr newarg))
(cons oldarg newarg)))
oldargs newargs)))
`(-> (tuple ,@newargs) ,(replace-vars (caddr f) renames))))
(if (and (pair? f) (eq? (car f) '->))
(if (pair? (cadr f))
(hygienic f) ; f is already anon function, nothing to do but hygienicize
(hygienic `(-> (tuple ,(cadr f)) ,(caddr f)))) ; canonicalize single arg to tuple
(let ((genargs (map (lambda (e) (gensy)) args))) ; formal parameters
(let ((genargs (map genarg args))) ; formal parameters
`(-> ,(cons 'tuple genargs) (call ,f ,@genargs)))))
(define (from-lambda f) ; convert (-> (tuple args...) (call func args...)) back to func
(if (and (pair? f) (eq? (car f) '->) (pair? (cadr f)) (eq? (caadr f) 'tuple)
Expand Down Expand Up @@ -1597,20 +1602,16 @@
fargs args)))
(let ,fbody ,@(reverse (fuse-lets fargs args '()))))))
(define (make-fuse f args) ; check for nested (fuse f args) exprs and combine
(define (expand-fuse e)
(if (and (pair? e) (eq? (car e) '|.|))
(let ((f (cadr e))
(x (caddr e)))
(if (getfield-field? x)
`(call (core getfield) ,(expand-forms f) ,(expand-forms x))
(make-fuse f (cdr x))))
(expand-forms e)))
(let ((args_ (map expand-fuse args)))
(define (dot-to-fuse e) ; convert e == (. f (tuple args)) to (fuse f args)
(if (and (pair? e) (eq? (car e) '|.|) (not (getfield-field? (caddr e))))
(make-fuse (cadr e) (cdaddr e))
e))
(let ((args_ (map dot-to-fuse args)))
(if (anyfuse? args_)
`(fuse ,(fuse-funcs (to-lambda f args) args_) ,(fuse-args args_))
`(fuse ,(to-lambda f args) ,args_))))
(let ((e (make-fuse f args))) ; an expression '(fuse func args)
`(call broadcast ,(expand-forms (from-lambda (cadr e))) ,@(caddr e))))
(expand-forms `(call broadcast ,(from-lambda (cadr e)) ,@(caddr e)))))

;; table mapping expression head to a function expanding that form
(define expand-table
Expand Down
1 change: 1 addition & 0 deletions test/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ let A = [sqrt(i)+j for i = 1:3, j=1:4]
end
let x = sin.(1:10)
@test atan2.((x->x+1).(x), (x->x+2).(x)) == atan2(x+1, x+2) == atan2(x.+1, x.+2)
@test sin.(atan2.([x+1,x+2]...)) == sin.(atan2.(x+1,x+2))
end
# Use side effects to check for loop fusion. Note that, due to #17314,
# a broadcasted function is currently called twice on the first element.
Expand Down

0 comments on commit 0c4b67e

Please sign in to comment.