Fix gethash indentation
[jscl.git] / src / hash-table.lisp
index 8125e9e..dc4f418 100644 (file)
 ;; You should have received a copy of the GNU General Public License
 ;; along with JSCL.  If not, see <http://www.gnu.org/licenses/>.
 
-;;; Javascript dictionaries are the natural way to implement Common
+;;; Plain Javascript objects are the natural way to implement Common
 ;;; Lisp hash tables. However, there is a big differences betweent
-;;; them which we need to work around. Javascript dictionaries require
-;;; the keys to be strings. To solve that, we map Lisp objects to
-;;; strings such that "equivalent" values map to the same string,
-;;; regarding the equality predicate used (one of `eq', `eql', `equal'
-;;; and `equalp').
+;;; them which we need to work around. Javascript objects require the
+;;; keys to be strings. To solve that, we map Lisp objects to strings
+;;; such that "equivalent" values map to the same string, regarding
+;;; the equality predicate used (one of `eq', `eql', `equal' and
+;;; `equalp').
 ;;;
 
+;;; Additionally, we want to iterate across the hash table
+;;; key-values. So we use a cons (key  . value)
+;;; as value in the Javascript object. It implicitly gives the
+;;; inverse mapping of strings to our objects.
 
 ;;; If a hash table has `eq' as test, we need to generate unique
 ;;; strings for each Lisp object. To do this, we tag the objects with
-;;; a `$$jscl_id' property. As a special case, numbers are not
-;;; objects, but they can be used for indexin a Javascript dictionary,
-;;; we do not need to tag them.
+;;; a `$$jscl_id' property. As a special case, numbers do not need to
+;;; be tagged, as they can be used to index Javascript objects.
 (defvar *eq-hash-counter* 0)
 (defun eq-hash (x)
   (cond
     `(hash-table ,hash-fn ,(new))))
 
 (defun gethash (key hash-table &optional default)
-  (let ((obj (caddr hash-table))
-        (hash (funcall (cadr hash-table) key)))
-    (values (oget obj hash)
-            (in hash obj))))
+  (let* ((obj (caddr hash-table))
+         (hash (funcall (cadr hash-table) key))
+         (exists (in hash obj)))
+    (if exists
+        (values (cdr (oget obj hash)) t)
+        (values default nil))))
 
 (defun sethash (new-value key hash-table)
   (let ((obj (caddr hash-table))
         (hash (funcall (cadr hash-table) key)))
-    (oset new-value obj hash)
+    (oset (cons key new-value) obj hash)
     new-value))
 
 
         (hash (funcall (cadr hash-table) key)))
     (prog1 (in hash obj)
       (delete-property hash obj))))
+
+
+(defun hash-table-count (hash-table)
+  (let ((count 0))
+    (map-for-in (lambda (x)
+                  (declare (ignore x))
+                  (incf count))
+                (caddr hash-table))
+    count))
+
+
+(defun maphash (function hash-table)
+  (map-for-in (lambda (x)
+               (funcall function (car x) (cdr x)))
+             (caddr hash-table))
+  nil)