safe-object.scm 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. ;;; This defines two Scheme 48 modules which each exports only a
  2. ;;; single value: An object which can't be modified from the outside.
  3. ;;; The first version is trivial. We just steal the parent.
  4. (define-structure safe-object-full (export full-safe-object)
  5. (open scheme
  6. prometheus)
  7. (begin
  8. (define fully-safe-object (*the-root-object* 'clone))
  9. (full-safe-object 'add-value-slot! 'fnord 'set-fnord! 23)
  10. (full-safe-object 'delete-slot! 'parent)))
  11. ;;; The second assumes you just want to hide a few of the messages of
  12. ;;; the parent object.
  13. ;;; The trick is to overwrite all modifying messages. Since the parent
  14. ;;; object might be used to modify us, we also hide it behind a
  15. ;;; private message name.
  16. (define-structure safe-object-partial (export partial-safe-object)
  17. (open scheme
  18. srfi-23
  19. prometheus)
  20. (begin
  21. (define partial-safe-object ((make-prometheus-root-object) 'clone))
  22. ;; The private parent message
  23. (let ((parent (list '*parent-message*)))
  24. (partial-safe-object 'add-value-slot! 'immutable 23)
  25. ;; Add our private parent
  26. (partial-safe-object 'add-parent-slot! parent (safe-object 'parent))
  27. ;; And delete the one added by the clone
  28. (partial-safe-object 'delete-slot! 'parent)
  29. ;; Overwrite all unneeded slots - since some messages need
  30. ;; others internally, we do a resend until we did overwrite all
  31. ;; slots:
  32. (let ((resend? #t))
  33. (for-each (lambda (msg)
  34. (partial-safe-object
  35. 'add-method-slot! msg
  36. (lambda (self resend . args)
  37. (if resend?
  38. (apply resend #f msg args)
  39. (error "Object is immutable!")))))
  40. '(add-slot-binding!
  41. remove-slot-bindings!
  42. clone
  43. add-value-slot!
  44. add-parent-slot!
  45. add-method-slot!
  46. delete-slot!
  47. slots->list))
  48. (set! resend? #f)))))