|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T h
Length: 8354 (0x20a2) Types: TextFile Names: »hash.scm.25«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/gnu-31mar87/scheme/scm/hash.scm.25«
;;; -*-Scheme-*- ;;; ;;; Copyright (c) 1984 Massachusetts Institute of Technology ;;; ;;; This material was developed by the Scheme project at the ;;; Massachusetts Institute of Technology, Department of ;;; Electrical Engineering and Computer Science. Permission to ;;; copy this software, to redistribute it, and to use it for any ;;; purpose is granted, subject to the following restrictions and ;;; understandings. ;;; ;;; 1. Any copy made of this software must include this copyright ;;; notice in full. ;;; ;;; 2. Users of this software agree to make their best efforts (a) ;;; to return to the MIT Scheme project any improvements or ;;; extensions that they make, so that these may be included in ;;; future releases; and (b) to inform MIT of noteworthy uses of ;;; this software. ;;; ;;; 3. All materials developed as a consequence of the use of ;;; this software shall duly acknowledge such use, in accordance ;;; with the usual standards of acknowledging credit in academic ;;; research. ;;; ;;; 4. MIT has made no warrantee or representation that the ;;; operation of this software will be error-free, and MIT is ;;; under no obligation to provide any services, by way of ;;; maintenance, update, or otherwise. ;;; ;;; 5. In conjunction with products arising from the use of this ;;; material, there shall be no use of the name of the ;;; Massachusetts Institute of Technology nor of any adaptation ;;; thereof in any advertising, promotional, or sales literature ;;; without prior written consent from MIT in each case. ;;; ;;;; Object Hashing (declare (usual-integrations)) \f ((make-primitive-procedure 'INITIALIZE-OBJECT-HASH) 313) (add-gc-daemon! (make-primitive-procedure 'REHASH-GC-DAEMON)) (define object-hash (make-primitive-procedure 'OBJECT-HASH)) (define object-unhash (make-primitive-procedure 'OBJECT-UNHASH)) (define hash-of-false (object-hash #!FALSE)) (define hash-of-false-number (primitive-datum hash-of-false)) (define (hash object) (primitive-datum (object-hash object))) (define (unhash n) (if (= n hash-of-false-number) #!FALSE (disjunction (object-unhash (make-non-pointer-object n)) (error "Not a valid hash number" 'UNHASH n)))) (define (valid-hash-number? n) (if (eq? n hash-of-false) #!TRUE (object-unhash n))) \f ;;;; Populations ;;; ;;; A population is a collection of objects. This collection ;;; has the property that if one of the objects in the collection ;;; is reclaimed as garbage, then it is no longer an element of ;;; the collection. (define make-population) (define population?) (let ((population-tag '(POPULATION))) (define population-of-populations (cons population-tag '())) (set! make-population (named-lambda (make-population) (let ((population (cons population-tag '()))) (add-to-population! population-of-populations population) population))) (set! population? (named-lambda (population? object) (conjunction (pair? object) (eq? (car object) population-tag)))) (define (gc-population! population) (set-cdr! population (delete-invalid-hash-numbers! (cdr population)))) (define delete-invalid-hash-numbers! (list-deletor! (lambda (hash-number) (not (valid-hash-number? hash-number))))) (define (gc-all-populations!) (gc-population! population-of-populations) (map-over-population population-of-populations gc-population!)) (add-secondary-gc-daemon! gc-all-populations!) ) (define (add-to-population! population object) (let ((n (object-hash object))) (if (not (memq n (cdr population))) (set-cdr! population (cons n (cdr population)))))) (define (remove-from-population! population object) (set-cdr! population (delq! (object-hash object) (cdr population)))) \f ;;; Population Mappings ;;; These have the effect of doing a GC-POPULATION! every time it is ;;; called, since the cost of doing so is very small. (define (map-over-population population procedure) (let loop ((previous population) (rest (cdr population))) (if (null? rest) '() (let ((unhash (object-unhash (car rest)))) (if (disjunction (eq? hash-of-false (car rest)) unhash) (cons (procedure unhash) (loop rest (cdr rest))) (sequence (set-cdr! previous (cdr rest)) (loop previous (cdr rest)))))))) (define (map-over-population! population procedure) (let loop ((previous population) (rest (cdr population))) (if (not (null? rest)) (let ((unhash (object-unhash (car rest)))) (if (disjunction (eq? hash-of-false (car rest)) unhash) (sequence (procedure unhash) (loop rest (cdr rest))) (sequence (set-cdr! previous (cdr rest)) (loop previous (cdr rest)))))))) (define (for-all-inhabitants? population predicate) (let loop ((previous population) (rest (cdr population))) (disjunction (null? rest) (let ((unhash (object-unhash (car rest)))) (if (disjunction (eq? hash-of-false (car rest)) unhash) (conjunction (predicate unhash) (loop rest (cdr rest))) (sequence (set-cdr! previous (cdr rest)) (loop previous (cdr rest)))))))) (define (exists-an-inhabitant? population predicate) (let loop ((previous population) (rest (cdr population))) (conjunction (not (null? rest)) (let ((unhash (object-unhash (car rest)))) (if (disjunction (eq? hash-of-false (car rest)) unhash) (disjunction (predicate unhash) (loop rest (cdr rest))) (sequence (set-cdr! previous (cdr rest)) (loop previous (cdr rest)))))))) \f ;;;; Properties (define 2D-put!) (define 2D-get) (define 2D-remove!) (define 2D-get-alist-x) (define 2D-get-alist-y) (let ((system-properties '())) (set! 2D-put! (named-lambda (2D-put! x y value) (let ((x-hash (object-hash x)) (y-hash (object-hash y))) (let ((bucket (assq x-hash system-properties))) (if bucket (let ((entry (assq y-hash (cdr bucket)))) (if entry (set-cdr! entry value) (set-cdr! bucket (cons (cons y-hash value) (cdr bucket))))) (set! system-properties (cons (cons x-hash (cons (cons y-hash value) '())) system-properties))))))) (set! 2D-get (named-lambda (2D-get x y) (let ((bucket (assq (object-hash x) system-properties))) (conjunction bucket (let ((entry (assq (object-hash y) (cdr bucket)))) (conjunction entry (cdr entry))))))) ;;; Returns TRUE iff an entry was removed. ;;; Removes the bucket if the entry removed was the only entry. (set! 2D-remove! (named-lambda (2D-remove! x y) (let ((bucket (assq (object-hash x) system-properties))) (conjunction bucket (sequence (set-cdr! bucket (del-assq! (object-hash y) (cdr bucket))) (if (null? (cdr bucket)) (set! system-properties (del-assq! (object-hash x) system-properties))) #!TRUE))))) ;;; This clever piece of code removes all invalid entries and buckets, ;;; and also removes any buckets which [subsequently] have no entries. (define (gc-system-properties!) (set! system-properties (delete-invalid-hash-numbers! system-properties))) (define delete-invalid-hash-numbers! (list-deletor! (lambda (bucket) (disjunction (not (valid-hash-number? (car bucket))) (sequence (set-cdr! bucket (delete-invalid-y! (cdr bucket))) (null? (cdr bucket))))))) (define delete-invalid-y! (list-deletor! (lambda (entry) (not (valid-hash-number? (car entry)))))) (add-secondary-gc-daemon! gc-system-properties!) \f (set! 2D-get-alist-x (named-lambda (2D-get-alist-x x) (let ((bucket (assq (object-hash x) system-properties))) (if bucket (let loop ((rest (cdr bucket))) (cond ((null? rest) '()) ((valid-hash-number? (caar rest)) (cons (cons (object-unhash (caar rest)) (cdar rest)) (loop (cdr rest)))) (else (loop (cdr rest))))) '())))) (set! 2D-get-alist-y (named-lambda (2D-get-alist-y y) (let ((y-hash (object-hash y))) (let loop ((rest system-properties)) (cond ((null? rest) '()) ((valid-hash-number? (caar rest)) (let ((entry (assq y-hash (cdar rest)))) (if entry (cons (cons (object-unhash (caar rest)) (cdr entry)) (loop (cdr rest))) (loop (cdr rest))))) (else (loop (cdr rest)))))))) )