diff --git a/include/mes/builtins.h b/include/mes/builtins.h index 6e485e0b..1b1c6546 100644 --- a/include/mes/builtins.h +++ b/include/mes/builtins.h @@ -71,6 +71,7 @@ struct scm *hashq_set_x (struct scm *table, struct scm *key, struct scm *value); struct scm *hash_set_x (struct scm *table, struct scm *key, struct scm *value); struct scm *hash_table_printer (struct scm *table); struct scm *make_hash_table (struct scm *x); +struct scm *hash_buckets (struct scm *table); /* src/lib.c */ struct scm *type_ (struct scm *x); struct scm *car_ (struct scm *x); diff --git a/mes/module/mes/scm.mes b/mes/module/mes/scm.mes index f9c473c4..97893a2e 100644 --- a/mes/module/mes/scm.mes +++ b/mes/module/mes/scm.mes @@ -2,6 +2,7 @@ ;;; GNU Mes --- Maxwell Equations of Software ;;; Copyright © 2016,2017,2018,2019 Jan (janneke) Nieuwenhuizen +;;; Copyright © 2022 Timothy Sample ;;; ;;; This file is part of GNU Mes. ;;; @@ -199,6 +200,21 @@ (define (hash-ref table key . rest) (core:hash-ref table key (and (pair? rest) (car rest)))) +(define (hash-map->list proc table) + (let ((buckets (hash-buckets table))) + (let loop ((i 0) (acc '())) + (if (>= i (vector-length buckets)) + (reverse! acc) + (let ((alist (vector-ref buckets i))) + (loop (+ i 1) + (if (eq? alist *unspecified*) + acc + (append-reverse (map (lambda (handle) + (proc (car handle) + (cdr handle))) + alist) + acc)))))))) + ;; Vector (define (vector . rest) (list->vector rest)) diff --git a/src/builtins.c b/src/builtins.c index faa5533c..d6f33d16 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -181,6 +181,7 @@ mes_builtins (struct scm *a) /*:((internal)) */ a = init_builtin (builtin_type, "hash-set!", 3, &hash_set_x, a); a = init_builtin (builtin_type, "hash-table-printer", 1, &hash_table_printer, a); a = init_builtin (builtin_type, "make-hash-table", -1, &make_hash_table, a); + a = init_builtin (builtin_type, "hash-buckets", 1, &hash_buckets, a); /* src/lib.c */ a = init_builtin (builtin_type, "core:type", 1, &type_, a); a = init_builtin (builtin_type, "core:car", 1, &car_, a); diff --git a/src/hash.c b/src/hash.c index 69a35d99..43aeb01b 100644 --- a/src/hash.c +++ b/src/hash.c @@ -216,3 +216,9 @@ make_hash_table (struct scm *x) /*:((arity . n)) */ } return make_hash_table_ (size); } + +struct scm * +hash_buckets (struct scm *table) +{ + return struct_ref_ (table, 4); +} diff --git a/tests/gc.test b/tests/gc.test index 9f958014..b2362bf5 100755 --- a/tests/gc.test +++ b/tests/gc.test @@ -1,6 +1,6 @@ #! /bin/sh # -*-scheme-*- -MES_ARENA=10000 +MES_ARENA=20000 MES_MAX_ARENA=$MES_ARENA export MES_ARENA export MES_MAX_ARENA diff --git a/tests/hash.test b/tests/hash.test index e158ea94..a3b31297 100755 --- a/tests/hash.test +++ b/tests/hash.test @@ -70,4 +70,14 @@ exec ${MES-bin/mes} --no-auto-compile -L ${0%/*} -L module -C module -e '(tests (and (eq? (hash-ref t "key" 'foo) 'foo) (eq? (hash-ref t "k2" 'foo) 'foo)))) +(pass-if "hash-map->list" + (let ((t (make-hash-table))) + (hash-set! t "first" 1) + (hash-set! t "second" 2) + (hash-set! t "third" 3) + (let ((a (hash-map->list cons t))) + (and (= (assoc-ref a "first") 1) + (= (assoc-ref a "second") 2) + (= (assoc-ref a "third") 3))))) + (result 'report)