- `((@ ,fn :apply) this ,arglist)))
-
-(defpsmacro destructuring-bind (vars expr &body body)
- ;; a simple implementation that for now only supports flat lists,
- ;; but does allow NIL bindings to indicate ignore (a la LOOP)
+ `((@ ,fn apply) this ,arglist)))
+
+(defun destructuring-wrap (arr n bindings body &key setf?)
+ (cond ((null bindings)
+ body)
+ ((atom bindings)
+ ;; dotted destructuring list
+ `(let ((,bindings (when (> (length ,arr) ,n)
+ ((@ ,arr slice) ,n))))
+ ,body))
+ (t (let ((var (car bindings))
+ (inner-body (destructuring-wrap arr (1+ n) (cdr bindings) body :setf? setf?)))
+ (cond ((null var) inner-body)
+ ((atom var) (if setf?
+ `(progn (setf ,var (aref ,arr ,n))
+ ,inner-body)
+ `(let ((,var (aref ,arr ,n)))
+ ,inner-body)))
+ (t `(,(if setf? 'dset 'destructuring-bind)
+ ,var (aref ,arr ,n)
+ ,inner-body)))))))
+
+(defpsmacro dset (bindings expr &body body)
+ (let ((arr (if (complex-js-expr? expr) (ps-gensym) expr)))
+ `(progn
+ ,@(unless (eq arr expr) `((setf ,arr ,expr)))
+ ,(destructuring-wrap arr 0 bindings (cons 'progn body) :setf? t))))
+
+(defpsmacro destructuring-bind (bindings expr &body body)