#lang racket
(require (only-in srfi/1 alist-cons alist-delete))
(provide *p-list* keyword-get putprop! remprop! symbol-plist)
(define *p-list* '())
(define (symbol-plist sym)
(cond ((assq sym *p-list*) => (lambda (x)
(cdr x)))
(else null)))
(define keyword-get
(case-lambda
((args kw not-found)
(cond ((memq kw (symbol-plist args))
=> (lambda (x)
(cadr x)))
(else not-found)))
((args kw) (keyword-get args kw #f))))
(define (remprop! sym indicator)
(and (keyword-get sym indicator)
(let-values (((head tail)
(let ((lst (symbol-plist sym)))
(split-at lst (index-of lst indicator eq?)))))
(let ((datum (append head (cddr tail))))
(set! *p-list* (alist-cons sym datum
(alist-delete sym *p-list*)))
#t))))
(define (putprop! atom val property p-list)
(when (keyword-get atom property)
(remprop! atom property))
(let ((datum (append `(,property ,val) (symbol-plist atom))))
(set! *p-list* (alist-cons atom datum
(alist-delete atom *p-list*)))
val))