|
1950 | 1950 | ,@(map expand-forms (cddr e))))
|
1951 | 1951 | (cons (car e) (map expand-forms (cdr e))))))
|
1952 | 1952 |
|
| 1953 | +(define (expand-tuple-destruct lhss x) |
| 1954 | + (define (sides-match? l r) |
| 1955 | + ;; l and r either have equal lengths, or r has a trailing ... |
| 1956 | + (cond ((null? l) (null? r)) |
| 1957 | + ((vararg? (car l)) #t) |
| 1958 | + ((null? r) #f) |
| 1959 | + ((vararg? (car r)) (null? (cdr r))) |
| 1960 | + (else (sides-match? (cdr l) (cdr r))))) |
| 1961 | + (if (and (pair? x) (pair? lhss) (eq? (car x) 'tuple) (not (any assignment? (cdr x))) |
| 1962 | + (not (has-parameters? (cdr x))) |
| 1963 | + (sides-match? lhss (cdr x))) |
| 1964 | + ;; (a, b, ...) = (x, y, ...) |
| 1965 | + (expand-forms |
| 1966 | + (tuple-to-assignments lhss x)) |
| 1967 | + ;; (a, b, ...) = other |
| 1968 | + (begin |
| 1969 | + ;; like memq, but if last element of lhss is (... sym), |
| 1970 | + ;; check against sym instead |
| 1971 | + (define (in-lhs? x lhss) |
| 1972 | + (if (null? lhss) |
| 1973 | + #f |
| 1974 | + (let ((l (car lhss))) |
| 1975 | + (cond ((and (pair? l) (eq? (car l) '|...|)) |
| 1976 | + (if (null? (cdr lhss)) |
| 1977 | + (eq? (cadr l) x) |
| 1978 | + (error (string "invalid \"...\" on non-final assignment location \"" |
| 1979 | + (cadr l) "\"")))) |
| 1980 | + ((eq? l x) #t) |
| 1981 | + (else (in-lhs? x (cdr lhss))))))) |
| 1982 | + ;; in-lhs? also checks for invalid syntax, so always call it first |
| 1983 | + (let* ((xx (if (or (and (not (in-lhs? x lhss)) (symbol? x)) |
| 1984 | + (ssavalue? x)) |
| 1985 | + x (make-ssavalue))) |
| 1986 | + (ini (if (eq? x xx) '() (list (sink-assignment xx (expand-forms x))))) |
| 1987 | + (n (length lhss)) |
| 1988 | + ;; skip last assignment if it is an all-underscore vararg |
| 1989 | + (n (if (> n 0) |
| 1990 | + (let ((l (last lhss))) |
| 1991 | + (if (and (vararg? l) (underscore-symbol? (cadr l))) |
| 1992 | + (- n 1) |
| 1993 | + n)) |
| 1994 | + n)) |
| 1995 | + (st (gensy))) |
| 1996 | + `(block |
| 1997 | + ,@(if (> n 0) `((local ,st)) '()) |
| 1998 | + ,@ini |
| 1999 | + ,@(map (lambda (i lhs) |
| 2000 | + (expand-forms |
| 2001 | + (if (vararg? lhs) |
| 2002 | + `(= ,(cadr lhs) (call (top rest) ,xx ,@(if (eq? i 0) '() `(,st)))) |
| 2003 | + (lower-tuple-assignment |
| 2004 | + (if (= i (- n 1)) |
| 2005 | + (list lhs) |
| 2006 | + (list lhs st)) |
| 2007 | + `(call (top indexed_iterate) |
| 2008 | + ,xx ,(+ i 1) ,@(if (eq? i 0) '() `(,st))))))) |
| 2009 | + (iota n) |
| 2010 | + lhss) |
| 2011 | + (unnecessary ,xx)))))) |
| 2012 | + |
1953 | 2013 | ;; move an assignment into the last statement of a block to keep more statements at top level
|
1954 | 2014 | (define (sink-assignment lhs rhs)
|
1955 | 2015 | (if (and (pair? rhs) (eq? (car rhs) 'block))
|
|
2102 | 2162 | (call (top setproperty!) ,aa ,bb ,rr)
|
2103 | 2163 | (unnecessary ,rr)))))
|
2104 | 2164 | ((tuple)
|
2105 |
| - ;; multiple assignment |
2106 | 2165 | (let ((lhss (cdr lhs))
|
2107 | 2166 | (x (caddr e)))
|
2108 |
| - (define (sides-match? l r) |
2109 |
| - ;; l and r either have equal lengths, or r has a trailing ... |
2110 |
| - (cond ((null? l) (null? r)) |
2111 |
| - ((vararg? (car l)) #t) |
2112 |
| - ((null? r) #f) |
2113 |
| - ((vararg? (car r)) (null? (cdr r))) |
2114 |
| - (else (sides-match? (cdr l) (cdr r))))) |
2115 |
| - (if (and (pair? x) (pair? lhss) (eq? (car x) 'tuple) (not (any assignment? (cdr x))) |
2116 |
| - (not (has-parameters? (cdr x))) |
2117 |
| - (sides-match? lhss (cdr x))) |
2118 |
| - ;; (a, b, ...) = (x, y, ...) |
2119 |
| - (expand-forms |
2120 |
| - (tuple-to-assignments lhss x)) |
2121 |
| - ;; (a, b, ...) = other |
2122 |
| - (begin |
2123 |
| - ;; like memq, but if last element of lhss is (... sym), |
2124 |
| - ;; check against sym instead |
2125 |
| - (define (in-lhs? x lhss) |
2126 |
| - (if (null? lhss) |
2127 |
| - #f |
2128 |
| - (let ((l (car lhss))) |
2129 |
| - (cond ((and (pair? l) (eq? (car l) '|...|)) |
2130 |
| - (if (null? (cdr lhss)) |
2131 |
| - (eq? (cadr l) x) |
2132 |
| - (error (string "invalid \"...\" on non-final assignment location \"" |
2133 |
| - (cadr l) "\"")))) |
2134 |
| - ((eq? l x) #t) |
2135 |
| - (else (in-lhs? x (cdr lhss))))))) |
2136 |
| - ;; in-lhs? also checks for invalid syntax, so always call it first |
2137 |
| - (let* ((xx (if (or (and (not (in-lhs? x lhss)) (symbol? x)) |
2138 |
| - (ssavalue? x)) |
2139 |
| - x (make-ssavalue))) |
2140 |
| - (ini (if (eq? x xx) '() (list (sink-assignment xx (expand-forms x))))) |
2141 |
| - (n (length lhss)) |
2142 |
| - ;; skip last assignment if it is an all-underscore vararg |
2143 |
| - (n (if (> n 0) |
2144 |
| - (let ((l (last lhss))) |
2145 |
| - (if (and (vararg? l) (underscore-symbol? (cadr l))) |
2146 |
| - (- n 1) |
2147 |
| - n)) |
2148 |
| - n)) |
2149 |
| - (st (gensy))) |
2150 |
| - `(block |
2151 |
| - ,@(if (> n 0) `((local ,st)) '()) |
2152 |
| - ,@ini |
2153 |
| - ,@(map (lambda (i lhs) |
2154 |
| - (expand-forms |
2155 |
| - (if (vararg? lhs) |
2156 |
| - `(= ,(cadr lhs) (call (top rest) ,xx ,@(if (eq? i 0) '() `(,st)))) |
2157 |
| - (lower-tuple-assignment |
2158 |
| - (if (= i (- n 1)) |
2159 |
| - (list lhs) |
2160 |
| - (list lhs st)) |
2161 |
| - `(call (top indexed_iterate) |
2162 |
| - ,xx ,(+ i 1) ,@(if (eq? i 0) '() `(,st))))))) |
2163 |
| - (iota n) |
2164 |
| - lhss) |
2165 |
| - (unnecessary ,xx))))))) |
| 2167 | + (if (has-parameters? lhss) |
| 2168 | + ;; property destructuring |
| 2169 | + (if (length= lhss 1) |
| 2170 | + (let* ((xx (if (symbol-like? x) x (make-ssavalue))) |
| 2171 | + (ini (if (eq? x xx) '() (list (sink-assignment xx (expand-forms x)))))) |
| 2172 | + `(block |
| 2173 | + ,@ini |
| 2174 | + ,@(map (lambda (field) |
| 2175 | + (if (not (symbol? field)) |
| 2176 | + (error (string "invalid assignment location \"" (deparse lhs) "\""))) |
| 2177 | + (expand-forms `(= ,field (call (top getproperty) ,xx (quote ,field))))) |
| 2178 | + (cdar lhss)) |
| 2179 | + (unnecessary ,xx))) |
| 2180 | + (error (string "invalid assignment location \"" (deparse lhs) "\""))) |
| 2181 | + ;; multiple assignment |
| 2182 | + (expand-tuple-destruct lhss x)))) |
2166 | 2183 | ((typed_hcat)
|
2167 | 2184 | (error "invalid spacing in left side of indexed assignment"))
|
2168 | 2185 | ((typed_vcat)
|
|
0 commit comments