eq-properties.scm 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. ;;;; Traditional LISP property lists
  21. ;;; extended to work on any kind of eq? data structure.
  22. (declare (usual-integrations))
  23. ;;; Property lists are a way of creating data that looks like a record
  24. ;;; structure without commiting to the fields that will be used until
  25. ;;; run time. The use of such flexible structures is frowned upon by
  26. ;;; most computer scientists, because it is hard to statically
  27. ;;; determine the bounds of the behavior of a program written using
  28. ;;; this stuff. But it makes it easy to write programs that confuse
  29. ;;; such computer scientists. I personally find it difficult to write
  30. ;;; without such crutches. -- GJS
  31. (define eq-properties (make-weak-eq-hash-table))
  32. (define (eq-put! node property value)
  33. (let ((plist (hash-table/get eq-properties node '())))
  34. (let ((vcell (assq property plist)))
  35. (if vcell
  36. (set-cdr! vcell value)
  37. (hash-table/put! eq-properties node
  38. (cons (cons property value)
  39. plist)))))
  40. node)
  41. (define (eq-get node property)
  42. (let ((plist (hash-table/get eq-properties node '())))
  43. (let ((vcell (assq property plist)))
  44. (if vcell
  45. (cdr vcell)
  46. #f))))
  47. (define (eq-rem! node . properties)
  48. (for-each
  49. (lambda (property)
  50. (let ((plist
  51. (hash-table/get eq-properties node '())))
  52. (let ((vcell (assq property plist)))
  53. (if vcell
  54. (hash-table/put! eq-properties node
  55. (delq! vcell plist))))))
  56. properties)
  57. node)
  58. (define (eq-adjoin! node property new)
  59. (eq-put! node property
  60. (lset-adjoin eq?
  61. (or (eq-get node property) '())
  62. new))
  63. node)
  64. (define (eq-plist node)
  65. (let ((plist (hash-table/get eq-properties node #f)))
  66. (if plist (cons node plist) #f)))
  67. (define (eq-clone! source target)
  68. (hash-table/put! eq-properties target
  69. (hash-table/get eq-properties source '()))
  70. target)
  71. (define (eq-label! node . plist)
  72. (let loop ((plist plist))
  73. (cond ((null? plist) node)
  74. ((null? (cdr plist)) (error "Malformed plist"))
  75. (else
  76. (eq-put! node (car plist) (cadr plist))
  77. (loop (cddr plist))))))
  78. ;;; Path names are built with properties.
  79. (define (eq-path path)
  80. (define (lp node)
  81. (if node
  82. (if (pair? path)
  83. (eq-get ((eq-path (cdr path)) node)
  84. (car path))
  85. node)
  86. #f))
  87. lp)