summaryrefslogtreecommitdiff
path: root/lib/zambyte/meta/json.sld
diff options
context:
space:
mode:
Diffstat (limited to 'lib/zambyte/meta/json.sld')
-rw-r--r--lib/zambyte/meta/json.sld116
1 files changed, 69 insertions, 47 deletions
diff --git a/lib/zambyte/meta/json.sld b/lib/zambyte/meta/json.sld
index afac535..0802f94 100644
--- a/lib/zambyte/meta/json.sld
+++ b/lib/zambyte/meta/json.sld
@@ -2,7 +2,6 @@
;; portable
(export json
define-json-record-type
- json->typeless-json
json-ref
json-value?
@@ -32,6 +31,11 @@
json-object->alist
json-list->list)
(import (scheme base))
+ (cond-expand
+ (gerbil (import (std srfi 1)
+ (only (gerbil core) and-let*)))
+ (else (import (srfi 1)
+ (srfi 2))))
;; portable
(begin
(define-syntax json
@@ -48,30 +52,6 @@
value
(error "json: not a json value" value)))))
- (define-syntax handle-field-declarations
- (syntax-rules ()
- ((_ (field accessor))
- (define (accessor obj)
- (json-object-ref obj 'field)))
- ((_ (field accessor mutator))
- (begin
- (define (accessor obj)
- (json-object-ref obj 'field))
- (define (mutator obj value)
- (json-object-set! (json-record->fields obj) 'field value))))))
-
- (define-syntax get-accessor
- (syntax-rules ()
- ((_ (field accessor rest ...))
- `(field . ,accessor))))
-
- (define-syntax get-mutator
- (syntax-rules ()
- ((_ (field _ mutator))
- `(field . ,mutator))
- ((_ (field _))
- `(field . #f))))
-
(define-syntax define-json-record-type
(syntax-rules ()
((_ type
@@ -83,46 +63,88 @@
(define-values (constructor predicate from-json-string)
((lambda ()
(define-record-type type
- (make-tag)
- pred?)
- (define tag (make-tag))
+ (internal-json-record fields ...)
+ internal-json-record?
+ field-declarations ...)
+
+ (define-syntax accessors
+ (syntax-rules ::: ()
+ ((_) '())
+ ((_ (name accessor . optional-mutator) rest :::)
+ (cons `(name . ,accessor) (accessors rest :::)))))
+
+ (define-syntax mutators
+ (syntax-rules ::: ()
+ ((_) '())
+ ((_ (name accessor) rest :::)
+ (mutators rest :::))
+ ((_ (name accessor mutator) rest :::)
+ (cons `(name . ,mutator) (mutators rest :::)))))
+
(define (constructor fields ...)
- (make-json-record 'type
- tag
- (json-object `(fields . ,fields) ...)
- from-json-string
- (list (get-accessor field-declarations) ...)
- (list (get-mutator field-declarations) ...)))
+ (define (typeless)
+ (json-object `(fields . ,fields) ...))
+ (json-record (internal-json-record fields ...)
+ 'type
+ typeless
+ (accessors field-declarations ...)
+ (mutators field-declarations ...)))
(define (predicate obj)
(cond
- ((json-record? obj) (pred? (json-record->tag obj)))
+ ((json-record? obj) (internal-json-record?
+ (json-record->internal-record obj)))
((json-object? obj) (and (json-object-contains-key? obj 'fields) ...))
(else #f)))
(define (from-json-string str)
(let ((json (string->json str)))
(if (json-record-from-string-allow-missing-keys)
- (make-json-record 'type
- tag
- (string->json str)
- from-json-string
- (list (get-accessor field-declarations) ...)
- (list (get-mutator field-declarations) ...))
+ ;; Assume that json-key-not-found is set to something sensible
+ (constructor (json-object-ref json 'fields) ...)
(parameterize ((json-key-not-found
(lambda ()
(error "key not found in json string when converting to a record" 'type))))
(constructor (json-object-ref json 'fields) ...)))))
(values constructor predicate from-json-string))))
- (handle-field-declarations field-declarations) ...))))
+ (define-syntax define-accessors-and-mutators
+ (syntax-rules ::: ()
+ ((_) (values))
+ ((_ (name accessor) rest :::)
+ (begin
+ (define (accessor json)
+ (if (json-record? json)
+ (or (and-let* ((pair (assoc 'name (json-record->accessors json)))
+ (acc (cdr pair)))
+ (acc (json-record->internal-record json)))
+ (error (string-append (symbol->string 'accessor) ": no accessor for field") (json-record->name json) 'name))
+ (json-object-ref json 'name)))
+ (define-accessors-and-mutators rest :::)))
+ ((_ (name accessor mutator) rest :::)
+ (begin
+ (define (accessor json)
+ (if (json-record? json)
+ (or (and-let* ((pair (assoc 'name (json-record->accessors json)))
+ (acc (cdr pair)))
+ (acc (json-record->internal-record json)))
+ (error (string-append (symbol->string 'accessor) ": no accessor for field") (json-record->name json) 'name))
+ (json-object-ref json 'name)))
+ (define (mutator json value)
+ (if (json-record? json)
+ (or (and-let* ((pair (assoc 'name (json-record->mutators json)))
+ (mut! (cdr pair)))
+ (mut! (json-record->internal-record json) value))
+ (error (string-append (symbol->string 'mutator) ": no mutator for field") (json-record->name json) 'name))
+ (json-object-set! json 'name value)))
+ (define-accessors-and-mutators rest :::)))))
+ (define-accessors-and-mutators field-declarations ...)))))
(define-record-type <json-record>
- (make-json-record name tag fields from-json-string accessors mutators)
+ (json-record internal-record name typeless accessors mutators)
json-record?
+ (internal-record json-record->internal-record)
(name json-record->name)
- (tag json-record->tag)
- (fields json-record->fields)
- (from-json-string json-record->from-json-string)
+ (typeless json-record->typeless)
(accessors json-record->accessors)
(mutators json-record->mutators))
@@ -131,7 +153,7 @@
(define (json->typeless-json json)
(cond
((json-record? json)
- (json->typeless-json (json-record->fields json)))
+ (json->typeless-json ((json-record->typeless json))))
((json-object? json)
(json-object-map (lambda (k v) (values k (json->typeless-json v))) json))
((json-list? json)