|
1418 | 1418 | `(call ,(cadr e) ,(expand-forms a) ,(expand-forms b)))))) |
1419 | 1419 |
|
1420 | 1420 | ;; convert `a+=b` to `a=a+b` |
1421 | | -(define (expand-update-operator- op lhs rhs declT) |
| 1421 | +(define (expand-update-operator- op op= lhs rhs declT) |
1422 | 1422 | (let ((e (remove-argument-side-effects lhs))) |
1423 | 1423 | `(block ,@(cdr e) |
1424 | 1424 | ,(if (null? declT) |
1425 | | - `(= ,(car e) (call ,op ,(car e) ,rhs)) |
1426 | | - `(= ,(car e) (call ,op (:: ,(car e) ,(car declT)) ,rhs)))))) |
| 1425 | + `(,op= ,(car e) (call ,op ,(car e) ,rhs)) |
| 1426 | + `(,op= ,(car e) (call ,op (:: ,(car e) ,(car declT)) ,rhs)))))) |
1427 | 1427 |
|
1428 | 1428 | (define (partially-expand-ref e) |
1429 | 1429 | (let ((a (cadr e)) |
|
1443 | 1443 | ,@(append stmts stuff) |
1444 | 1444 | (call getindex ,arr ,@new-idxs)))))) |
1445 | 1445 |
|
1446 | | -(define (expand-update-operator op lhs rhs . declT) |
| 1446 | +(define (expand-update-operator op op= lhs rhs . declT) |
1447 | 1447 | (cond ((and (pair? lhs) (eq? (car lhs) 'ref)) |
1448 | 1448 | ;; expand indexing inside op= first, to remove "end" and ":" |
1449 | 1449 | (let* ((ex (partially-expand-ref lhs)) |
1450 | 1450 | (stmts (butlast (cdr ex))) |
1451 | 1451 | (refex (last (cdr ex))) |
1452 | 1452 | (nuref `(ref ,(caddr refex) ,@(cdddr refex)))) |
1453 | 1453 | `(block ,@stmts |
1454 | | - ,(expand-update-operator- op nuref rhs declT)))) |
| 1454 | + ,(expand-update-operator- op op= nuref rhs declT)))) |
1455 | 1455 | ((and (pair? lhs) (eq? (car lhs) '|::|)) |
1456 | 1456 | ;; (+= (:: x T) rhs) |
1457 | 1457 | (let ((e (remove-argument-side-effects (cadr lhs))) |
1458 | 1458 | (T (caddr lhs))) |
1459 | 1459 | `(block ,@(cdr e) |
1460 | | - ,(expand-update-operator op (car e) rhs T)))) |
| 1460 | + ,(expand-update-operator op op= (car e) rhs T)))) |
1461 | 1461 | (else |
1462 | | - (expand-update-operator- op lhs rhs declT)))) |
| 1462 | + (expand-update-operator- op op= lhs rhs declT)))) |
1463 | 1463 |
|
1464 | 1464 | (define (lower-update-op e) |
1465 | 1465 | (expand-forms |
1466 | | - (expand-update-operator |
1467 | | - (let ((str (string (car e)))) |
1468 | | - (symbol (string.sub str 0 (- (length str) 1)))) |
1469 | | - (cadr e) |
1470 | | - (caddr e)))) |
| 1466 | + (let ((str (string (car e)))) |
| 1467 | + (expand-update-operator |
| 1468 | + (symbol (string.sub str 0 (- (length str) 1))) |
| 1469 | + (if (= (string.char str 0) #\.) '.= '=) |
| 1470 | + (cadr e) |
| 1471 | + (caddr e))))) |
1471 | 1472 |
|
1472 | 1473 | (define (expand-and e) |
1473 | 1474 | (let ((e (cdr (flatten-ex '&& e)))) |
|
1546 | 1547 | (cadr expr) ;; eta reduce `x->f(x)` => `f` |
1547 | 1548 | `(-> ,argname (block ,@splat ,expr))))) |
1548 | 1549 |
|
1549 | | -(define (getfield-field? x) ; whether x from (|.| f x) is a getfield call |
1550 | | - (or (eq? (car x) 'quote) (eq? (car x) 'inert) (eq? (car x) '$))) |
1551 | | - |
1552 | | -;; fuse nested calls to f.(args...) into a single broadcast call |
1553 | | -(define (expand-fuse-broadcast f args) |
| 1550 | +; fuse nested calls to expr == f.(args...) into a single broadcast call, |
| 1551 | +; or a broadcast! call if lhs is non-null. |
| 1552 | +(define (expand-fuse-broadcast lhs rhs) |
1554 | 1553 | (define (fuse? e) (and (pair? e) (eq? (car e) 'fuse))) |
1555 | 1554 | (define (anyfuse? exprs) |
1556 | 1555 | (if (null? exprs) #f (if (fuse? (car exprs)) #t (anyfuse? (cdr exprs))))) |
|
1594 | 1593 | oldarg)) |
1595 | 1594 | fargs args))) |
1596 | 1595 | (let ,fbody ,@(reverse (fuse-lets fargs args '())))))) |
1597 | | - (define (make-fuse f args) ; check for nested (fuse f args) exprs and combine |
1598 | | - (define (split-kwargs args) ; return (cons keyword-args positional-args) extracted from args |
1599 | | - (define (sk args kwargs pargs) |
1600 | | - (if (null? args) |
1601 | | - (cons kwargs pargs) |
1602 | | - (if (kwarg? (car args)) |
1603 | | - (sk (cdr args) (cons (car args) kwargs) pargs) |
1604 | | - (sk (cdr args) kwargs (cons (car args) pargs))))) |
1605 | | - (if (has-parameters? args) |
1606 | | - (sk (reverse (cdr args)) (cdar args) '()) |
1607 | | - (sk (reverse args) '() '()))) |
1608 | | - (define (dot-to-fuse e) ; convert e == (. f (tuple args)) to (fuse f args) |
1609 | | - (if (and (pair? e) (eq? (car e) '|.|) (not (getfield-field? (caddr e)))) |
1610 | | - (make-fuse (cadr e) (cdaddr e)) |
1611 | | - e)) |
1612 | | - (let* ((kws.args (split-kwargs args)) |
1613 | | - (kws (car kws.args)) |
1614 | | - (args (cdr kws.args)) ; fusing occurs on positional args only |
1615 | | - (args_ (map dot-to-fuse args))) |
1616 | | - (if (anyfuse? args_) |
1617 | | - `(fuse ,(fuse-funcs (to-lambda f args kws) args_) ,(fuse-args args_)) |
1618 | | - `(fuse ,(to-lambda f args kws) ,args_)))) |
| 1596 | + (define (dot-to-fuse e) ; convert e == (. f (tuple args)) to (fuse f args) |
| 1597 | + (define (make-fuse f args) ; check for nested (fuse f args) exprs and combine |
| 1598 | + (define (split-kwargs args) ; return (cons keyword-args positional-args) extracted from args |
| 1599 | + (define (sk args kwargs pargs) |
| 1600 | + (if (null? args) |
| 1601 | + (cons kwargs pargs) |
| 1602 | + (if (kwarg? (car args)) |
| 1603 | + (sk (cdr args) (cons (car args) kwargs) pargs) |
| 1604 | + (sk (cdr args) kwargs (cons (car args) pargs))))) |
| 1605 | + (if (has-parameters? args) |
| 1606 | + (sk (reverse (cdr args)) (cdar args) '()) |
| 1607 | + (sk (reverse args) '() '()))) |
| 1608 | + (let* ((kws.args (split-kwargs args)) |
| 1609 | + (kws (car kws.args)) |
| 1610 | + (args (cdr kws.args)) ; fusing occurs on positional args only |
| 1611 | + (args_ (map dot-to-fuse args))) |
| 1612 | + (if (anyfuse? args_) |
| 1613 | + `(fuse ,(fuse-funcs (to-lambda f args kws) args_) ,(fuse-args args_)) |
| 1614 | + `(fuse ,(to-lambda f args kws) ,args_)))) |
| 1615 | + (if (and (pair? e) (eq? (car e) '|.|)) |
| 1616 | + (let ((f (cadr e)) (x (caddr e))) |
| 1617 | + (if (or (eq? (car x) 'quote) (eq? (car x) 'inert) (eq? (car x) '$)) |
| 1618 | + `(call (core getfield) ,f ,x) |
| 1619 | + (make-fuse f (cdr x)))) |
| 1620 | + e)) |
1619 | 1621 | ; given e == (fuse lambda args), compress the argument list by removing (pure) |
1620 | 1622 | ; duplicates in args, inlining literals, and moving any varargs to the end: |
1621 | 1623 | (define (compress-fuse e) |
1622 | 1624 | (define (findfarg arg args fargs) ; for arg in args, return corresponding farg |
1623 | 1625 | (if (eq? arg (car args)) |
1624 | 1626 | (car fargs) |
1625 | 1627 | (findfarg arg (cdr args) (cdr fargs)))) |
1626 | | - (let ((f (cadr e)) |
1627 | | - (args (caddr e))) |
1628 | | - (define (cf old-fargs old-args new-fargs new-args renames varfarg vararg) |
1629 | | - (if (null? old-args) |
1630 | | - (let ((nfargs (if (null? varfarg) new-fargs (cons varfarg new-fargs))) |
1631 | | - (nargs (if (null? vararg) new-args (cons vararg new-args)))) |
1632 | | - `(fuse (-> (tuple ,@(reverse nfargs)) ,(replace-vars (caddr f) renames)) |
1633 | | - ,(reverse nargs))) |
1634 | | - (let ((farg (car old-fargs)) (arg (car old-args))) |
1635 | | - (cond |
1636 | | - ((and (vararg? farg) (vararg? arg)) ; arg... must be the last argument |
1637 | | - (if (null? varfarg) |
1638 | | - (cf (cdr old-fargs) (cdr old-args) |
1639 | | - new-fargs new-args renames farg arg) |
1640 | | - (if (eq? (cadr vararg) (cadr arg)) |
| 1628 | + (if (fuse? e) |
| 1629 | + (let ((f (cadr e)) |
| 1630 | + (args (caddr e))) |
| 1631 | + (define (cf old-fargs old-args new-fargs new-args renames varfarg vararg) |
| 1632 | + (if (null? old-args) |
| 1633 | + (let ((nfargs (if (null? varfarg) new-fargs (cons varfarg new-fargs))) |
| 1634 | + (nargs (if (null? vararg) new-args (cons vararg new-args)))) |
| 1635 | + `(fuse (-> (tuple ,@(reverse nfargs)) ,(replace-vars (caddr f) renames)) |
| 1636 | + ,(reverse nargs))) |
| 1637 | + (let ((farg (car old-fargs)) (arg (car old-args))) |
| 1638 | + (cond |
| 1639 | + ((and (vararg? farg) (vararg? arg)) ; arg... must be the last argument |
| 1640 | + (if (null? varfarg) |
1641 | 1641 | (cf (cdr old-fargs) (cdr old-args) |
1642 | | - new-fargs new-args (cons (cons (cadr farg) (cadr varfarg)) renames) |
1643 | | - varfarg vararg) |
1644 | | - (error "multiple splatted args cannot be fused into a single broadcast")))) |
1645 | | - ((number? arg) ; inline numeric literals |
1646 | | - (cf (cdr old-fargs) (cdr old-args) |
1647 | | - new-fargs new-args |
1648 | | - (cons (cons farg arg) renames) |
1649 | | - varfarg vararg)) |
1650 | | - ((and (symbol? arg) (memq arg new-args)) ; combine duplicate args |
1651 | | - ; (note: calling memq for every arg is O(length(args)^2) ... |
1652 | | - ; ... would be better to replace with a hash table if args is long) |
1653 | | - (cf (cdr old-fargs) (cdr old-args) |
1654 | | - new-fargs new-args |
1655 | | - (cons (cons farg (findfarg arg new-args new-fargs)) renames) |
1656 | | - varfarg vararg)) |
1657 | | - (else |
1658 | | - (cf (cdr old-fargs) (cdr old-args) |
1659 | | - (cons farg new-fargs) (cons arg new-args) renames varfarg vararg)))))) |
1660 | | - (cf (cdadr f) args '() '() '() '() '()))) |
1661 | | - (let ((e (compress-fuse (make-fuse f args)))) ; an expression '(fuse func args) |
1662 | | - (expand-forms `(call broadcast ,(from-lambda (cadr e)) ,@(caddr e))))) |
| 1642 | + new-fargs new-args renames farg arg) |
| 1643 | + (if (eq? (cadr vararg) (cadr arg)) |
| 1644 | + (cf (cdr old-fargs) (cdr old-args) |
| 1645 | + new-fargs new-args (cons (cons (cadr farg) (cadr varfarg)) renames) |
| 1646 | + varfarg vararg) |
| 1647 | + (error "multiple splatted args cannot be fused into a single broadcast")))) |
| 1648 | + ((number? arg) ; inline numeric literals |
| 1649 | + (cf (cdr old-fargs) (cdr old-args) |
| 1650 | + new-fargs new-args |
| 1651 | + (cons (cons farg arg) renames) |
| 1652 | + varfarg vararg)) |
| 1653 | + ((and (symbol? arg) (memq arg new-args)) ; combine duplicate args |
| 1654 | + ; (note: calling memq for every arg is O(length(args)^2) ... |
| 1655 | + ; ... would be better to replace with a hash table if args is long) |
| 1656 | + (cf (cdr old-fargs) (cdr old-args) |
| 1657 | + new-fargs new-args |
| 1658 | + (cons (cons farg (findfarg arg new-args new-fargs)) renames) |
| 1659 | + varfarg vararg)) |
| 1660 | + (else |
| 1661 | + (cf (cdr old-fargs) (cdr old-args) |
| 1662 | + (cons farg new-fargs) (cons arg new-args) renames varfarg vararg)))))) |
| 1663 | + (cf (cdadr f) args '() '() '() '() '())) |
| 1664 | + e)) ; (not (fuse? e)) |
| 1665 | + (let ((e (compress-fuse (dot-to-fuse rhs)))) ; an expression '(fuse func args) if expr is a dot call |
| 1666 | + (if (fuse? e) |
| 1667 | + (if (null? lhs) |
| 1668 | + (expand-forms `(call broadcast ,(from-lambda (cadr e)) ,@(caddr e))) |
| 1669 | + (expand-forms `(call broadcast! ,(from-lambda (cadr e)) ,lhs ,@(caddr e)))) |
| 1670 | + (if (null? lhs) |
| 1671 | + (expand-forms e) |
| 1672 | + (expand-forms `(call broadcast! identity ,lhs ,e)))))) |
1663 | 1673 |
|
1664 | 1674 | ;; table mapping expression head to a function expanding that form |
1665 | 1675 | (define expand-table |
|
1697 | 1707 |
|
1698 | 1708 | '|.| |
1699 | 1709 | (lambda (e) ; e = (|.| f x) |
1700 | | - (let ((f (cadr e)) |
1701 | | - (x (caddr e))) |
1702 | | - (if (getfield-field? x) |
1703 | | - `(call (core getfield) ,(expand-forms f) ,(expand-forms x)) |
1704 | | - ; otherwise, came from f.(args...) --> broadcast(f, args...), |
1705 | | - ; where we want to fuse with any nested broadcast calls. |
1706 | | - (expand-fuse-broadcast f (cdr x))))) |
| 1710 | + (expand-fuse-broadcast '() e)) |
| 1711 | + |
| 1712 | + '.= |
| 1713 | + (lambda (e) |
| 1714 | + (expand-fuse-broadcast (cadr e) (caddr e))) |
1707 | 1715 |
|
1708 | 1716 | '|<:| syntactic-op-to-call |
1709 | 1717 | '|>:| syntactic-op-to-call |
|
2008 | 2016 | '%= lower-update-op |
2009 | 2017 | '.%= lower-update-op |
2010 | 2018 | '|\|=| lower-update-op |
| 2019 | + '|.\|=| lower-update-op |
2011 | 2020 | '&= lower-update-op |
| 2021 | + '.&= lower-update-op |
2012 | 2022 | '$= lower-update-op |
2013 | 2023 | '<<= lower-update-op |
| 2024 | + '.<<= lower-update-op |
2014 | 2025 | '>>= lower-update-op |
| 2026 | + '.>>= lower-update-op |
2015 | 2027 | '>>>= lower-update-op |
| 2028 | + '.>>>= lower-update-op |
2016 | 2029 |
|
2017 | 2030 | ': |
2018 | 2031 | (lambda (e) |
|
0 commit comments