Commits

Moritz Heidkamp  committed a38743c

properly handle function argument / var clashes, too

  • Participants
  • Parent commits 8c943d8

Comments (0)

Files changed (2)

                 (list sym*))
                (else sym*)))))))
 
+(define (compile-fn*-args args)
+  (let loop ((args (clojure-vector-elements args)))
+    (if (null? args)
+        (values '()'())
+        (let ((var (clojure-symbol->var-name (car args))))
+          (if (eq? '& var)
+              (cond ((null? (cdr args))
+                     (error 'clojure-compile
+                            "missing rest argument name"
+                            args))
+                    ((not (null? (cddr args)))
+                     (error 'clojure-compile
+                            "too many arguments after rest argument"
+                            args))
+                    ((clojure-symbol->var-name (cadr args)) =>
+                     (lambda (var)
+                       (if (eq? '& var)
+                           (error 'clojure-compile
+                                  "invalid rest argument name"
+                                  var)
+                           (values (list var) (local-var-name var))))))
+              (receive (locals args) (loop (cdr args))
+                (values (cons var locals)
+                        (cons (local-var-name var) args))))))))
+
 (define (compile-fn*-tail args body)
-  (cons
-   (let loop ((args (clojure-vector-elements args)))
-     (if (null? args)
-         '()
-         (let ((var (clojure-symbol->var-name (car args))))
-           (if (eq? '& var)
-               (cond ((null? (cdr args))
-                      (error 'clojure-compile
-                             "missing rest argument name"
-                             args))
-                     ((not (null? (cddr args)))
-                      (error 'clojure-compile
-                             "too many arguments after rest argument"
-                             args))
-                     ((clojure-symbol->var-name (cadr args)) =>
-                      (lambda (var)
-                        (if (eq? '& var)
-                            (error 'clojure-compile
-                                   "invalid rest argument name"
-                                   var)
-                            var))))
-               (cons var (loop (cdr args)))))))
-   (map clojure-compile body)))
+  (receive (locals args) (compile-fn*-args args)
+    (cons args
+          (parameterize ((local-scope (append locals (local-scope))))
+            (map clojure-compile body)))))
 
 (define (compile-fn* form)
   (match form

File tests/run.scm

            "(def bar (fn* ([] 1) ([x] x) ([x & y] y)))"
            "(list (bar) (bar 2) (bar 2 3))"))
   (test-group "named"
-    (test* 4 "((fn* self ([x] (self x x)) ([x y] (+ x y))) 2)")))
+    (test* 4 "((fn* self ([x] (self x x)) ([x y] (+ x y))) 2)"))
+  (test* '(1 2)
+         "(def x 1)"
+         "((fn* [x] (list user/x x)) 2)"))
 
 (test-group "syntax-quote"
   (test* (make-clojure-symbol 'user 'bar) "`bar")