CAR and CDR work for NIL object
[jscl.git] / test.lisp
index a77545a..7652409 100644 (file)
--- a/test.lisp
+++ b/test.lisp
@@ -66,6 +66,8 @@
 (defun truncate (x y) (floor (/ x y)))
 
 (defun cons (x y ) (cons x y))
+(defun consp (x) (consp x))
+
 (defun car (x) (car x))
 (defun caar (x) (car (car x)))
 (defun cadr (x) (car (cdr x)))
     (t
      (cons (car list) (remove x (cdr list))))))
 
+(defun remove-if (func list)
+  (cond
+    ((null list)
+     nil)
+    ((funcall func (car list))
+     (remove-if func (cdr list)))
+    (t
+     (cons (car list) (remove-if func (cdr list))))))
+
+(defun remove-if-not (func list)
+  (cond
+    ((null list)
+     nil)
+    ((funcall func (car list))
+     (cons (car list) (remove-if-not func (cdr list))))
+    (t
+     (remove-if-not func (cdr list)))))
+
 (defun digit-char-p (x)
   (if (and (<= #\0 x) (<= x #\9))
       (- x #\0)
 (defun mark-binding-as-declared (b)
   (setcar (cdddr b) t))
 
-(let ((counter 0))
-  (defun gvarname (symbol)
-    (concat "v" (integer-to-string (incf counter))))
-
-  (defun lookup-variable (symbol env)
-    (or (assoc symbol env)
-        (assoc symbol *env*)
-        (let ((name (symbol-name symbol))
-              (binding (make-binding symbol 'variable (gvarname symbol) nil)))
-          (push binding *env*)
-          (push (lambda ()
-                  (unless (binding-declared (assoc symbol *env*))
-                    (error (concat "Undefined variable `" name "'"))))
-                *compilation-unit-checks*)
-          binding)))
-
-  (defun lookup-variable-translation (symbol env)
-    (binding-translation (lookup-variable symbol env)))
-
-  (defun extend-local-env (args env)
-    (append (mapcar (lambda (symbol)
-                      (make-binding symbol 'variable (gvarname symbol) t))
-                    args)
-            env)))
-
-(let ((counter 0))
-  (defun lookup-function (symbol env)
-    (or (assoc symbol env)
-        (assoc symbol *fenv*)
-        (let ((name (symbol-name symbol))
-              (binding
-               (make-binding symbol
-                             'function
-                             (concat "f" (integer-to-string (incf counter)))
-                             nil)))
-          (push binding *fenv*)
-          (push (lambda ()
-                  (unless (binding-declared (assoc symbol *fenv*))
-                    (error (concat "Undefined function `" name "'"))))
-                *compilation-unit-checks*)
-          binding)))
-
-  (defun lookup-function-translation (symbol env)
-    (binding-translation (lookup-function symbol env))))
+(defvar *variable-counter* 0)
+(defun gvarname (symbol)
+  (concat "v" (integer-to-string (incf *variable-counter*))))
+
+(defun lookup-variable (symbol env)
+  (or (assoc symbol env)
+      (assoc symbol *env*)
+      (let ((name (symbol-name symbol))
+            (binding (make-binding symbol 'variable (gvarname symbol) nil)))
+        (push binding *env*)
+        (push (lambda ()
+                (unless (binding-declared (assoc symbol *env*))
+                  (error (concat "Undefined variable `" name "'"))))
+              *compilation-unit-checks*)
+        binding)))
+
+(defun lookup-variable-translation (symbol env)
+  (binding-translation (lookup-variable symbol env)))
+
+(defun extend-local-env (args env)
+  (append (mapcar (lambda (symbol)
+                    (make-binding symbol 'variable (gvarname symbol) t))
+                  args)
+          env))
+
+(defvar *function-counter* 0)
+(defun lookup-function (symbol env)
+  (or (assoc symbol env)
+      (assoc symbol *fenv*)
+      (let ((name (symbol-name symbol))
+            (binding
+             (make-binding symbol
+                           'function
+                           (concat "f" (integer-to-string (incf *function-counter*)))
+                           nil)))
+        (push binding *fenv*)
+        (push (lambda ()
+                (unless (binding-declared (assoc symbol *fenv*))
+                  (error (concat "Undefined function `" name "'"))))
+              *compilation-unit-checks*)
+        binding)))
+
+(defun lookup-function-translation (symbol env)
+  (binding-translation (lookup-function symbol env)))
 
 
 (defvar *toplevel-compilations* nil)
                           ", cdr: "
                          (literal->js (cdr sexp)) "}"))))
 
-(let ((counter 0))
-  (defun literal (form)
-    (let ((var (concat "l" (integer-to-string (incf counter)))))
-      (push (concat "var " var " = " (literal->js form)) *toplevel-compilations*)
-      var)))
+(defvar *literal-counter* 0)
+(defun literal (form)
+  (let ((var (concat "l" (integer-to-string (incf *literal-counter*)))))
+    (push (concat "var " var " = " (literal->js form)) *toplevel-compilations*)
+    var))
 
 (define-compilation quote (sexp)
   (literal sexp))
      (lookup-function-translation x fenv))))
 
 #+common-lisp
-(defmacro eval-when-compile (&body body)
+c(defmacro eval-when-compile (&body body)
   `(eval-when (:compile-toplevel :load-toplevel :execute)
      ,@body))
 
            "; return (typeof tmp == 'object' && 'car' in tmp);})()")))
 
 (define-compilation car (x)
-  (concat "(" (ls-compile x env fenv) ").car"))
+  (concat "(function () { var tmp = " (ls-compile x env fenv)
+          "; return tmp === " (ls-compile nil nil nil) "? "
+          (ls-compile nil nil nil)
+          ": tmp.car; })()"))
 
 (define-compilation cdr (x)
-  (concat "(" (ls-compile x env fenv) ").cdr"))
+  (concat "(function () { var tmp = " (ls-compile x env fenv)
+          "; return tmp === " (ls-compile nil nil nil) "? "
+          (ls-compile nil nil nil)
+          ": tmp.cdr; })()"))
 
 (define-compilation setcar (x new)
   (concat "((" (ls-compile x env fenv) ").car = " (ls-compile new env fenv) ")"))
   (setq *toplevel-compilations* nil)
   (let ((code (ls-compile sexp nil nil)))
     (prog1
-        (concat
+        (concat  #+common-lisp (concat "/* " (princ-to-string sexp) " */")
                 (join (mapcar (lambda (x) (concat x ";" *newline*))
                               *toplevel-compilations*)
                "")
   (defun bootstrap ()
     (ls-compile-file "lispstrack.lisp" "lispstrack.js")))
 
-
 ;;; ----------------------------------------------------------
 
 (defmacro with-compilation-unit (&rest body)
-  `(prog1 (progn ,@body)
+  `(prog1
+       (progn
+         (setq *compilation-unit-checks* nil)
+         (setq *env* (remove-if-not #'binding-declared *env*))
+         (setq *fenv* (remove-if-not #'binding-declared *fenv*))
+         ,@body)
      (dolist (check *compilation-unit-checks*)
-       (funcall check))
-     (setq *compilation-unit-checks* nil)))
+       (funcall check))))
 
 (defun eval (x)
   (let ((code
              (ls-compile-toplevel x nil nil))))
     (js-eval code)))
 
+
 ;; Set the initial global environment to be equal to the host global
 ;; environment at this point of the compilation.
 (eval-when-compile
   (let ((c1 (ls-compile `(setq *fenv* ',*fenv*) nil nil))
-        (c2 (ls-compile `(setq  *env*  ',*env*) nil nil)))
+        (c2 (ls-compile `(setq *env* ',*env*) nil nil))
+        (c3 (ls-compile `(setq *variable-counter* ',*variable-counter*) nil nil))
+        (c4 (ls-compile `(setq *function-counter* ',*function-counter*) nil nil))
+        (c5 (ls-compile `(setq *literal-counter* ',*literal-counter*) nil nil)))
     (setq *toplevel-compilations*
-          (append *toplevel-compilations* (list c1 c2)))))
+          (append *toplevel-compilations* (list c1 c2 c3 c4 c5)))))
 
 (js-eval
  (concat "var lisp = {};"