Permalink
Browse files

move function declarations to the top of enclosing scope (uglifyjs is…

…sue #68)
  • Loading branch information...
1 parent c47a23e commit e64f5c52e146de611b380ff0cf54dacc699a0cf2 @mishoo committed Dec 17, 2010
Showing with 66 additions and 46 deletions.
  1. +13 −0 src/constants.lisp
  2. +40 −33 src/mangle.lisp
  3. +13 −13 src/walker.lisp
View
@@ -94,3 +94,16 @@
(defun curry (func &rest a1)
(lambda (&rest a2)
(apply func (append a1 a2))))
+
+(defstruct topval (v nil))
+
+(defun mymap (func list)
+ (iter (for i in list)
+ (for v = (funcall func i))
+ (finally (return (nconc one two)))
+ ;; because iterate has a nasty bug: if you try to collect into
+ ;; the *same* list, sometimes at start, sometimes at end,
+ ;; you'll get a "nil is not a cons" error.
+ (if (typep v 'topval)
+ (collect (topval-v v) into one at start)
+ (collect v into two))))
View
@@ -115,39 +115,46 @@
name)))
(with-new-scope
- (let ((new-ast (ast-walk (ast)
- (ast-case expr
- ((:function :defun) (name args body) `(,(car expr)
- ,(when name (wrap-name name :define t))
- ,@(with-new-scope
- (list (mapcar (lambda (arg)
- (wrap-name arg :define t)) args)
- (mapcar #'walk body)))))
- (:with ()
- (foreach-scope-parent (*current-scope* s)
- (setf (scope-uses-with s) t))
- nil)
- ((:var :const) (defs) `(,(car expr)
- ,(mapcar (lambda (def)
- `(,(wrap-name (car def) :define t)
- ,@(walk (cdr def))))
- defs)))
- (:try (tr ca fi)
- (when ca
- ;; only when the catch block is present we need to deal with names
- `(:try ,(walk tr)
- (,(wrap-name (car ca) :define t)
- ,@(walk (cdr ca)))
- ,(walk fi))))
- (:name (name)
- (when (string= name "eval")
- (setf having-eval (pushnew *current-scope* having-eval)))
- `(:name ,(wrap-name name :reference t)))
- (:for-in (has-var name hash body)
- `(:for-in ,has-var
- ,(wrap-name name :define has-var :reference (not has-var))
- ,(walk hash)
- ,(walk body)))))))
+ (let* ((stack nil)
+ (new-ast (ast-walk (ast expr walk stack)
+ (ast-case expr
+ ((:function :defun) (name args body)
+ (let ((ret `(,(car expr)
+ ,(when name (wrap-name name :define t))
+ ,@(with-new-scope
+ (list (mapcar (lambda (arg)
+ (wrap-name arg :define t)) args)
+ (mymap #'walk body))))))
+ (when (eq (car expr) :defun)
+ (ast-case (cadr stack)
+ ((:toplevel :function :defun) ()
+ (make-topval :v ret))
+ (t () ret)))))
+ (:with ()
+ (foreach-scope-parent (*current-scope* s)
+ (setf (scope-uses-with s) t))
+ nil)
+ ((:var :const) (defs) `(,(car expr)
+ ,(mapcar (lambda (def)
+ `(,(wrap-name (car def) :define t)
+ ,@(walk (cdr def))))
+ defs)))
+ (:try (tr ca fi)
+ (when ca
+ ;; only when the catch block is present we need to deal with names
+ `(:try ,(walk tr)
+ (,(wrap-name (car ca) :define t)
+ ,@(walk (cdr ca)))
+ ,(walk fi))))
+ (:name (name)
+ (when (string= name "eval")
+ (setf having-eval (pushnew *current-scope* having-eval)))
+ `(:name ,(wrap-name name :reference t)))
+ (:for-in (has-var name hash body)
+ `(:for-in ,has-var
+ ,(wrap-name name :define has-var :reference (not has-var))
+ ,(walk hash)
+ ,(walk body)))))))
;; propagate "uses-eval" to toplevel scope
(dolist (scope having-eval)
View
@@ -18,17 +18,17 @@
(prog1
(or (progn ,@body)
(ast-case ,expr
- ((:function :defun) (name args body) `(,(car ,expr) ,name ,args ,(mapcar #',walk body)))
+ ((:function :defun) (name args body) `(,(car ,expr) ,name ,args ,(mymap #',walk body)))
((:var :const) (defs) (list (car ,expr)
- (mapcar (lambda (def)
- `(,(car def) ,@(,walk (cdr def)))) defs)))
- (:array (a) `(:array ,(mapcar #',walk a)))
+ (mymap (lambda (def)
+ `(,(car def) ,@(,walk (cdr def)))) defs)))
+ (:array (a) `(:array ,(mymap #',walk a)))
(:assign (op left right) `(:assign ,op ,(,walk left) ,(,walk right)))
(:atom (a) `(:atom ,a))
(:binary (op left right) `(:binary ,op ,(,walk left) ,(,walk right)))
- (:block (body) `(:block ,(mapcar #',walk body)))
+ (:block (body) `(:block ,(mymap #',walk body)))
(:break (label) `(:break ,label))
- (:call (expr args) `(:call ,(,walk expr) ,(mapcar #',walk args)))
+ (:call (expr args) `(:call ,(,walk expr) ,(mymap #',walk args)))
(:conditional (cond then else) `(:conditional ,(,walk cond) ,(,walk then) ,(,walk else)))
(:continue (label) `(:continue ,label))
(:do (cond body) `(:do ,(,walk cond) ,(,walk body)))
@@ -38,22 +38,22 @@
(:if (cond then else) `(:if ,(,walk cond) ,(,walk then) ,(,walk else)))
(:label (label body) `(:label ,label ,(,walk body)))
(:name (name) `(:name ,name))
- (:new (ctor args) `(:new ,(,walk ctor) ,(mapcar #',walk args)))
+ (:new (ctor args) `(:new ,(,walk ctor) ,(mymap #',walk args)))
(:num (n) `(:num ,n))
- (:object (props) `(:object ,(mapcar (lambda (def)
- `(,(car def) ,@(,walk (cdr def)))) props)))
+ (:object (props) `(:object ,(mymap (lambda (def)
+ `(,(car def) ,@(,walk (cdr def)))) props)))
(:regexp (pattern modifiers) `(:regexp ,pattern ,modifiers))
(:return (expr) `(:return ,(,walk expr)))
(:seq (one two) `(:seq ,(,walk one) ,(,walk two)))
(:stat (stmt) `(:stat ,(,walk stmt)))
(:string (str) `(:string ,str))
(:sub (expr sub) `(:sub ,(,walk expr) ,(,walk sub)))
(:switch (expr body) `(:switch ,(,walk expr)
- ,(mapcar (lambda (branch)
- `(,(walk (car branch))
- ,@(mapcar #',walk (cdr branch)))) body)))
+ ,(mymap (lambda (branch)
+ `(,(walk (car branch))
+ ,@(mymap #',walk (cdr branch)))) body)))
(:throw (expr) `(:throw ,(,walk expr)))
- (:toplevel (body) `(:toplevel ,(mapcar #',walk body)))
+ (:toplevel (body) `(:toplevel ,(mymap #',walk body)))
(:try (tr ca fi) `(:try ,(,walk tr)
,(when ca `(,(car ca) ,@(,walk (cdr ca))))
,(when fi (,walk fi))))

0 comments on commit e64f5c5

Please sign in to comment.