aboutsummaryrefslogtreecommitdiff
path: root/module/hnh/util/object.scm
diff options
context:
space:
mode:
Diffstat (limited to 'module/hnh/util/object.scm')
-rw-r--r--module/hnh/util/object.scm41
1 files changed, 40 insertions, 1 deletions
diff --git a/module/hnh/util/object.scm b/module/hnh/util/object.scm
index 813a59ce..68703e1e 100644
--- a/module/hnh/util/object.scm
+++ b/module/hnh/util/object.scm
@@ -112,11 +112,35 @@
(datum->syntax stx))))
#'(name name-get name-set)))))
+;;; Name of the created accessor
+(define (accessor-name field)
+ (syntax-case field ()
+ ((name kvs ...)
+ (cond ((kv-ref #'(kvs ...) accessor:)
+ => identity)
+ (else #'name)))
+ (name #'name)))
+
+;;; Name of the created lens
+(define (lens-name field)
+ (syntax-case field ()
+ ((name kvs ...)
+ (cond ((kv-ref #'(kvs ...) lens:)
+ => identity)
+ (else (->> (syntax->datum #'name)
+ (format #f "~a*")
+ string->symbol
+ (datum->syntax field)))))
+ (name (->> (syntax->datum #'name)
+ (format #f "~a*")
+ string->symbol
+ (datum->syntax field)))))
+
;; Accessors are procedures for getting and setting fields in records
(define-syntax (build-accessor stx)
(syntax-case stx ()
((_ type-name (name kvs ...))
- #'(define name
+ #`(define #,(accessor-name #'(name kvs ...))
(case-lambda ((datum)
((field-get type-name name) datum))
((datum new-value)
@@ -126,10 +150,23 @@
;; while keeping name bound to the accessor in the outer scope.
(let ((name new-value))
(validator name (name kvs ...)))
+
((field-set type-name name) datum new-value)))))
+
((_ type-name name) #'(build-accessor type-name (name)))))
+(define (build-lenses stx fields)
+ (map (lambda (field)
+ (with-syntax ((lens* (lens-name field))
+ (accessor (accessor-name field)))
+ #'(define (lens* object)
+ (lambda (op)
+ (accessor object
+ (op (accessor object)))))))
+ fields))
+
+
(define (syntax-name field)
(syntax-case field ()
((name kvs ...)
@@ -187,6 +224,8 @@
;; Field accessors
(build-accessor name field) ...
+ #,@(build-lenses stx #'(field ...))
+
;; if printer in attribute
#,@(cond ((kv-ref #'(attribute ...) printer:)
=> (lambda (printer)