(ftype 'FUNCTION)
(form 'FUNCTION_STATEMENT)
(name "")
- params body
+ params rest-p
+ body
lp rp)))
"AST node for a function declaration.
-The `params' field is a lisp list of nodes. Each node is either a simple
+The `params' field is a Lisp list of nodes. Each node is either a simple
`js2-name-node', or if it's a destructuring-assignment parameter, a
`js2-array-node' or `js2-object-node'."
ftype ; FUNCTION, GETTER or SETTER
form ; FUNCTION_{STATEMENT|EXPRESSION|EXPRESSION_STATEMENT}
name ; function name (a `js2-name-node', or nil if anonymous)
- params ; a lisp list of destructuring forms or simple name nodes
+ params ; a Lisp list of destructuring forms or simple name nodes
+ rest-p ; if t, the last parameter is rest parameter
body ; a `js2-block-node' or expression node (1.8 only)
lp ; position of arg-list open-paren, or nil if omitted
rp ; position of arg-list close-paren, or nil if omitted
(:constructor nil)
(:constructor make-js2-array-comp-loop-node (&key (type js2-FOR)
(pos js2-ts-cursor)
- len
- iterator
- object
- in-pos
+ len iterator
+ object in-pos
foreach-p
each-pos
+ forof-p
lp rp)))
"AST subtree for each 'for (foo in bar)' loop in an array comprehension.")
(js2-visit-ast (js2-array-comp-loop-node-object n) v))
(defun js2-print-array-comp-loop (n i)
- (insert "for (")
+ (insert "for ")
+ (when (js2-array-comp-loop-node-foreach-p n) (insert "each "))
+ (insert "(")
(js2-print-ast (js2-array-comp-loop-node-iterator n) 0)
- (insert " in ")
+ (if (js2-array-comp-loop-node-forof-p n)
+ (insert " of ")
+ (insert " in "))
(js2-print-ast (js2-array-comp-loop-node-object n) 0)
(insert ")"))
(js2-consume-token)
t))
-(defsubst js2-valid-prop-name-token (tt)
+ (defun js2-match-contextual-kwd (name)
+ "Consume and return t if next token is `js2-NAME', and its
+ string is NAME. Returns nil and does nothing otherwise."
+ (if (or (/= (js2-peek-token) js2-NAME)
+ (not (string= js2-ts-string name)))
+ nil
+ (js2-consume-token)
+ (js2-record-face 'font-lock-keyword-face)
+ t))
+
+(defun js2-valid-prop-name-token (tt)
(or (= tt js2-NAME)
- (and js2-allow-keywords-as-property-names
- (plusp tt)
- (aref js2-kwd-tokens tt))))
+ (when (and js2-allow-keywords-as-property-names
+ (plusp tt)
+ (aref js2-kwd-tokens tt))
+ (js2-save-name-token-data js2-token-beg (js2-token-name tt))
+ t)))
-(defsubst js2-match-prop-name ()
+(defun js2-match-prop-name ()
"Consume token and return t if next token is a valid property name.
It's valid if it's a js2-NAME, or `js2-allow-keywords-as-property-names'
is non-nil and it's a keyword token."
(cond
;; destructuring param
((or (= tt js2-LB) (= tt js2-LC))
- (setq param (js2-parse-primary-expr-lhs))
+ (when default-found
+ (js2-report-error "msg.no.default.after.default.param"))
+ (setq param (js2-parse-destruct-primary-expr))
(js2-define-destruct-symbols param
js2-LP
- 'js2-function-param-face)
+ 'js2-function-param)
(push param params))
- ;; simple name
+ ;; variable name
(t
+ (when (and (>= js2-language-version 200)
+ (js2-match-token js2-TRIPLEDOT)
+ (not rest-param-at))
+ ;; to report errors if there are more parameters
+ (setq rest-param-at (length params)))
(js2-must-match js2-NAME "msg.no.parm")
- (js2-record-face 'js2-function-param-face)
+ (js2-record-face 'js2-function-param)
(setq param (js2-create-name-node))
(js2-define-symbol js2-LP js2-ts-string param)
+ ;; default parameter value
+ (when (or (and default-found
+ (not rest-param-at)
+ (js2-must-match js2-ASSIGN
+ "msg.no.default.after.default.param"
+ (js2-node-pos param)
+ (js2-node-len param)))
+ (and (>= js2-language-version 200)
+ (js2-match-token js2-ASSIGN)))
+ (let* ((pos (js2-node-pos param))
+ (tt js2-current-token)
+ (op-pos (- js2-token-beg pos))
+ (left param)
+ (right (js2-parse-assign-expr))
+ (len (- (js2-node-end right) pos)))
+ (setq param (make-js2-assign-node
+ :type tt :pos pos :len len :op-pos op-pos
+ :left left :right right)
+ default-found t)
+ (js2-node-add-children param left right)))
(push param params)))
+ (when (and rest-param-at (> (length params) (1+ rest-param-at)))
+ (js2-report-error "msg.param.after.rest" nil
+ (js2-node-pos param) (js2-node-len param)))
while
(js2-match-token js2-COMMA))
- (if (js2-must-match js2-RP "msg.no.paren.after.parms")
- (setf (js2-function-node-rp fn-node) (- js2-token-beg pos)))
+ (when (js2-must-match js2-RP "msg.no.paren.after.parms")
+ (setf (js2-function-node-rp fn-node) (- js2-token-beg pos)))
+ (when rest-param-at
+ (setf (js2-function-node-rest-p fn-node) t))
(dolist (p params)
(js2-node-add-children fn-node p)
(push p (js2-function-node-params fn-node))))))
(let ((pos js2-token-beg)
(end js2-token-end)
(after-lb-or-comma t)
- after-comma
- tt
- elems
- pn
+ after-comma tt elems pn
(continue t))
- (unless js2-is-in-lhs
+ (unless js2-is-in-destructuring
(js2-push-scope (make-js2-scope))) ; for array comp
(while continue
(setq tt (js2-peek-token))