preserves/implementations/racket/preserves/preserves-schema/unparser.rkt

79 lines
3.3 KiB
Racket

#lang racket/base
(provide definition-unparser
Ref-unparser-name)
(require preserves)
(require racket/match)
(require (only-in racket/syntax format-symbol))
(require (only-in racket/list append-map))
(require "type.rkt")
(require "gen/schema.rkt")
(define (definition-unparser name def)
(define ty (definition-ty def))
`(define (,(format-symbol "~a->preserves" name) input)
,(match def
[(Definition-or p0 p1 pN)
`(match input
,@(for/list [(named-alt (in-list (list* p0 p1 pN)))
(alt-ty (in-list (map cadr (ty-union-variants ty))))]
(match-define (NamedAlternative variant-label-str pattern) named-alt)
`[,(deconstruct (format-symbol "~a-~a" name variant-label-str) #t alt-ty)
,(pattern->unparser pattern 'src)]))]
[(Definition-and p0 p1 pN)
`(match input
[,(deconstruct name #f ty)
(merge-preserves
(lambda (a b) (if (equal? a b) a (error 'merge-preserves "Cannot merge")))
,@(append-map (lambda (named-pat)
(match named-pat
[(NamedPattern-anonymous (Pattern-SimplePattern _)) '()]
[_ (list (pattern->unparser named-pat 'src))]))
(list* p0 p1 pN)))])]
[(Definition-Pattern pattern)
`(match input
[,(deconstruct name #f ty)
,(pattern->unparser pattern 'src)])])))
(define (deconstruct name wrap? ty)
(match ty
[(ty-record fields) `(,name ,@(map escape (map car fields)))]
[(ty-unit) `(,name)]
[_ (if wrap? `(,name src) 'src)]))
(define (pattern->unparser pattern src-stx)
(match (unwrap pattern)
[(NamedSimplePattern_ n p) (pattern->unparser p (escape n))]
[(SimplePattern-any) src-stx]
[(SimplePattern-atom _) src-stx]
[(SimplePattern-embedded _interface) `(embedded (:embedded->preserves ,src-stx))]
[(SimplePattern-lit v) `',v]
[(SimplePattern-seqof variable-pat)
`(for/list [(item (in-list ,src-stx))] ,(pattern->unparser variable-pat 'item))]
[(SimplePattern-setof pat)
`(for/set [(item (in-set ,src-stx))] ,(pattern->unparser pat 'item))]
[(SimplePattern-dictof key-pat value-pat)
`(for/hash [((key value) (in-dict ,src-stx))]
(values ,(pattern->unparser key-pat 'key)
,(pattern->unparser value-pat 'value)))]
[(SimplePattern-Ref r)
`(,(Ref-unparser-name r) ,src-stx)]
[(CompoundPattern-rec label-pat fields-pat)
`(record ,(pattern->unparser label-pat src-stx) ,(pattern->unparser fields-pat src-stx))]
[(CompoundPattern-tuple named-pats)
`(list ,@(for/list [(p (in-list named-pats))] (pattern->unparser p src-stx)))]
[(CompoundPattern-tuple* fixed-named-pats variable-named-pat)
`(list* ,@(for/list [(p (in-list fixed-named-pats))] (pattern->unparser p src-stx))
,(pattern->unparser variable-named-pat src-stx))]
[(CompoundPattern-dict entries)
`(hash ,@(append-map (lambda (entry)
(list `',(car entry)
(pattern->unparser (cdr entry) src-stx)))
(sorted-dict-entries entries)))]))
(define (Ref-unparser-name r)
(match-define (Ref module-path name) r)
(format-symbol "~a~a->preserves" (module-path-prefix module-path) name))