|
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))
|
|
2079 | 2139 | (call (top setproperty!) ,aa ,bb ,rr)
|
2080 | 2140 | (unnecessary ,rr)))))
|
2081 | 2141 | ((tuple)
|
2082 |
| - ;; multiple assignment |
2083 | 2142 | (let ((lhss (cdr lhs))
|
2084 | 2143 | (x (caddr e)))
|
2085 |
| - (define (sides-match? l r) |
2086 |
| - ;; l and r either have equal lengths, or r has a trailing ... |
2087 |
| - (cond ((null? l) (null? r)) |
2088 |
| - ((vararg? (car l)) #t) |
2089 |
| - ((null? r) #f) |
2090 |
| - ((vararg? (car r)) (null? (cdr r))) |
2091 |
| - (else (sides-match? (cdr l) (cdr r))))) |
2092 |
| - (if (and (pair? x) (pair? lhss) (eq? (car x) 'tuple) (not (any assignment? (cdr x))) |
2093 |
| - (not (has-parameters? (cdr x))) |
2094 |
| - (sides-match? lhss (cdr x))) |
2095 |
| - ;; (a, b, ...) = (x, y, ...) |
2096 |
| - (expand-forms |
2097 |
| - (tuple-to-assignments lhss x)) |
2098 |
| - ;; (a, b, ...) = other |
2099 |
| - (begin |
2100 |
| - ;; like memq, but if last element of lhss is (... sym), |
2101 |
| - ;; check against sym instead |
2102 |
| - (define (in-lhs? x lhss) |
2103 |
| - (if (null? lhss) |
2104 |
| - #f |
2105 |
| - (let ((l (car lhss))) |
2106 |
| - (cond ((and (pair? l) (eq? (car l) '|...|)) |
2107 |
| - (if (null? (cdr lhss)) |
2108 |
| - (eq? (cadr l) x) |
2109 |
| - (error (string "invalid \"...\" on non-final assignment location \"" |
2110 |
| - (cadr l) "\"")))) |
2111 |
| - ((eq? l x) #t) |
2112 |
| - (else (in-lhs? x (cdr lhss))))))) |
2113 |
| - ;; in-lhs? also checks for invalid syntax, so always call it first |
2114 |
| - (let* ((xx (if (or (and (not (in-lhs? x lhss)) (symbol? x)) |
2115 |
| - (ssavalue? x)) |
2116 |
| - x (make-ssavalue))) |
2117 |
| - (ini (if (eq? x xx) '() (list (sink-assignment xx (expand-forms x))))) |
2118 |
| - (n (length lhss)) |
2119 |
| - ;; skip last assignment if it is an all-underscore vararg |
2120 |
| - (n (if (> n 0) |
2121 |
| - (let ((l (last lhss))) |
2122 |
| - (if (and (vararg? l) (underscore-symbol? (cadr l))) |
2123 |
| - (- n 1) |
2124 |
| - n)) |
2125 |
| - n)) |
2126 |
| - (st (gensy))) |
2127 |
| - `(block |
2128 |
| - ,@(if (> n 0) `((local ,st)) '()) |
2129 |
| - ,@ini |
2130 |
| - ,@(map (lambda (i lhs) |
2131 |
| - (expand-forms |
2132 |
| - (if (vararg? lhs) |
2133 |
| - `(= ,(cadr lhs) (call (top rest) ,xx ,@(if (eq? i 0) '() `(,st)))) |
2134 |
| - (lower-tuple-assignment |
2135 |
| - (if (= i (- n 1)) |
2136 |
| - (list lhs) |
2137 |
| - (list lhs st)) |
2138 |
| - `(call (top indexed_iterate) |
2139 |
| - ,xx ,(+ i 1) ,@(if (eq? i 0) '() `(,st))))))) |
2140 |
| - (iota n) |
2141 |
| - lhss) |
2142 |
| - (unnecessary ,xx))))))) |
| 2144 | + (if (has-parameters? lhss) |
| 2145 | + ;; property destructuring |
| 2146 | + (if (length= lhss 1) |
| 2147 | + (let* ((xx (if (symbol-like? x) x (make-ssavalue))) |
| 2148 | + (ini (if (eq? x xx) '() (list (sink-assignment xx (expand-forms x)))))) |
| 2149 | + `(block |
| 2150 | + ,@ini |
| 2151 | + ,@(map (lambda (field) |
| 2152 | + (if (not (symbol? field)) |
| 2153 | + (error (string "invalid assignment location \"" (deparse lhs) "\""))) |
| 2154 | + (expand-forms `(= ,field (call (top getproperty) ,xx (quote ,field))))) |
| 2155 | + (cdar lhss)) |
| 2156 | + (unnecessary ,xx))) |
| 2157 | + (error (string "invalid assignment location \"" (deparse lhs) "\""))) |
| 2158 | + ;; multiple assignment |
| 2159 | + (expand-tuple-destruct lhss x)))) |
2143 | 2160 | ((typed_hcat)
|
2144 | 2161 | (error "invalid spacing in left side of indexed assignment"))
|
2145 | 2162 | ((typed_vcat)
|
|
0 commit comments