PasteRack.org
Paste # 21026
2023-10-28 11:47:38

Fork as a new paste.

Paste viewed 445 times.


Embed:

  1. #lang racket
  2.  
  3. (require (for-syntax racket/match
  4.                      syntax/parse))
  5.  
  6. (begin-for-syntax
  7.   ; the description of a fact which expands to an implication
  8.   (define-splicing-syntax-class fact
  9.     #:datum-literals (-- = $)
  10.  
  11.     ; match some rhs in (hash-table ('rhs rhs) _ ...)
  12.     ; written as `rhs --`
  13.     (pattern {~seq rhs*:id --}
  14.       #:with rhs #'rhs*
  15.       #:with lhs #''rhs*)
  16.  
  17.     ; match some rhs, lhs in (hash-table ('rhs lhs) _ ...)
  18.     ; written as `rhs = lhs`
  19.     (pattern {~seq rhs*:id (~optional {~seq = lhs*:expr})}
  20.       #:with rhs #'(~? lhs* _)
  21.       #:with lhs #''rhs*)
  22.  
  23.     ; match some rhs, lhs in (hash-table (rhs lhs) _ ...)
  24.     ; written as `$ rhs = lhs`
  25.     (pattern {~seq $ rhs*:expr (~optional {~seq = lhs*:expr})}
  26.       #:with rhs #'(~? lhs* _)
  27.       #:with lhs #'rhs*))
  28.  
  29.   ; an implication, i.e. k implies v, in (hash-table (k v) _ ...)
  30.   ; in general, (hash-table (f0 (hash-table (f1 (⋯ fn))))) is written
  31.   ; `f0 : f1 :  : fn` for some facts f0, ⋯, fn
  32.   (define-splicing-syntax-class impl
  33.     #:datum-literals (:)
  34.     (pattern {~seq fact:fact}
  35.       #:with norm #'(fact.lhs fact.rhs))
  36.  
  37.     ; we want to keep the "top" of the implication bare, and wrap the deeper facts in (hash-table ...)
  38.     (pattern {~seq fact:fact : facts-or-conj:impl->hash}
  39.       #:with norm #'(fact.lhs (and fact.rhs facts-or-conj.norm))))
  40.  
  41.   (define-splicing-syntax-class impl->hash
  42.     (pattern impl:impl
  43.       #:with ooo  #'(... ...)
  44.       #:with norm #'(hash-table impl.norm _ ooo))
  45.  
  46.     ; a trailing conjunction is allowed
  47.     (pattern impl:conj
  48.       #:with norm #'(extract impl)))
  49.  
  50.   ; not being used yet
  51.   (define-splicing-syntax-class ellipsis
  52.     #:datum-literals (each some with))
  53.  
  54.   ; the conjunction of implications, eventually expanded to (hash-table (k u) (l v)  (m w))
  55.   ; for some implications p = (k u), q = (l v), ⋯, r = (m w)
  56.   ; in general, (hash-table p q  r) is written
  57.   ; `[p × q ×  × r]`, optionally with a trailing `@ z` to capture the rest of the hash-table
  58.   (define-syntax-class conj
  59.     #:datum-literals (× @)
  60.     (pattern [impl0:impl {~seq × impl:impl} ... (~optional {~seq @ rest*:expr})]
  61.       #:with norm #'(impl0.norm impl.norm  ...)
  62.       #:with rest #'(~? rest* _))))
  63.  
  64. (define-match-expander extract
  65.   (lambda (stx)
  66.     (syntax-parse stx
  67.       #:datum-literals (list-of)
  68.  
  69.       ; match a list of similar hash-tables
  70.       [(_ list-of conj*:conj)
  71.        #:with ooo #'(... ...)
  72.        #'(list (extract conj*) ooo)]
  73.  
  74.       ; match a single hash-table
  75.       [(_ conj*:conj)
  76.        #:with ooo #'(... ...)
  77.        #'(app (match-lambda
  78.                 [(and hash (hash-table (~@ . conj*.norm) (k v) ooo))
  79.                  (cons hash (make-hash (map cons k v)))] [_ #f])
  80.               (cons (hash-table (~@ . conj*.norm)) conj*.rest))])))
  81.  
  82. (match (list #hash((windows . #hash((wash  . #hash((john . #hash((4 . h)))
  83.                                                    (mary . #hash((1 . h)))))))
  84.                    (veranda . #hash((scrub . #hash((john . #hash((3 . h)))))))
  85.                    (cellars . #hash((scrub . #hash((john . #hash((3 . h)))))))
  86.                    (day     . "1896-02-03"))
  87.  
  88.              #hash((windows . #hash((wash  . #hash((jill . #hash((3   . h)))
  89.                                                    (jack . #hash((2   . h)))))))
  90.                    (veranda . #hash((scrub . #hash((jess . #hash((1   . h)))))))
  91.                    (cellars . #hash((scrub . #hash((jess . #hash((0.5 . h)))))))
  92.                    (day     . "1896-02-10"))
  93.  
  94.              #hash((windows . #hash((wash  . #hash((jill . #hash((3 . h)))
  95.                                                    (jack . #hash((2 . h)))))))
  96.                    (veranda . #hash((scrub . #hash((jess . #hash((5 . h)))))))
  97.                    (cellars . #hash((scrub . #hash((jess . #hash((2 . h)))))))
  98.                    (day     . "1896-02-17")))
  99.   [(extract list-of
  100.     [ windows
  101.     : wash --
  102.     : [ $ (or 'jill 'mary)
  103.       : $ time-jill+mary = 'h
  104.  
  105.       × $ (or 'jack 'john)
  106.       : $ time-jack+john = 'h]
  107.     × veranda
  108.     : scrub = veranda-scrub
  109.     × cellars
  110.     : scrub = cellars-scrub
  111.     @ rest])
  112.    ;---
  113.    (displayln wash)
  114.    (displayln time-jill+mary)
  115.    (displayln time-jack+john)
  116.    (displayln veranda-scrub)
  117.    (displayln cellars-scrub)
  118.    (displayln rest)]
  119.   [_ #f])

=>