PasteRack.org
Paste # 3646
2014-04-15 11:20:53

Fork as a new paste.

Paste viewed 38 times.


Embed:

example of #; paren match failure in emacs

  1. #lang racket
  2. (define (a/equal? d₀ d₁ store-spaces μ)
  3.   (define/match (egal-equal? a₀ a₁)
  4.     [((Address-Egal space a) (Address-Egal space a))
  5.      (match (hash-ref μ a₀ 'ω)
  6.        [1 #t]
  7.        ['ω 'b.⊤]
  8.        [0 (error 'a/match "Live address with count 0: ~a (Counts ~a) (Store ~a)" a₀ μ store-spaces)])]
  9.     [(_ _) #f])
  10.  
  11.   (define (ffun-equal? f₀ f₁)
  12.     (if abs?
  13.         (b∧ (ffun-⊑? f₀ f₁)
  14.             (ffun-⊑? f₁ f₀))
  15.         (concrete-ffun-equal? f₀ f₁)))
  16.  
  17.   ;; Slow path: linearly look for a key "equal" to k with "equal" values.
  18.   (define (slow-equal k v f)
  19.     (for/b∨ ([(k₁ v₁) (in-dict f)])
  20.             (b∧ (a/equal? k k₁)
  21.                 (a/equal? v v₁))))
  22.  
  23.   (define (ffun-⊑? dom f₀ f₁)
  24.     (for/b∧ ([(k v) (in-dict f₀)])
  25.             (match (dict-ref f₁ k -unmapped)
  26.               [(== -unmapped eq?) (slow-equal k v f₁)]
  27.               [v₁ ;; fast path: check the structurally equal key
  28.                (b∨ (a/equal? v₀ v₁)
  29.                    (slow-equal k v f₁))])))
  30.  
  31.   (define (concrete-ffun-equal? m₀ m₁)
  32.     (and (= (dict-count m₀) (dict-count m₁))
  33.          (for/b∧ ([(k₀ v₀) (in-dict m₀)])
  34.                  (match (dict-ref m₁ k₀ -unmapped)
  35.                    ;; Concrete domains w/o structural equality are actually abstract.
  36.                    ;; Note this is different from the concrete semantics.
  37.                    [(== -unmapped eq?) #f]
  38.                    ;; Note we don't use b∨ with the slow path
  39.                    [v₁ (a/equal? v₀ v₁)]))))
  40.  
  41.   (define (discrete-ffun-equal? m₀ m₁)
  42.     (and (= (dict-count m₀) (dict-count m₁))
  43.          (for/b∧ ([(k₀ v₀) (in-dict m₀)])
  44.                  (match (dict-ref m₁ k₀ -unmapped)
  45.                    [(== -unmapped eq?) #f]
  46.                    [v₁ (b∧
  47.                         ;; Discrete maps get structural equality on keys, but can only be
  48.                         ;; truly equal if the key has cardinality 1.
  49.                         (if (∣γ∣>1 k₀ μ) 'b.⊤ #t)
  50.                         (a/equal? v₀ v₁))]))))
  51.  
  52.   (define (equal-step d₀ d₁)
  53.     (match* (d₀ d₁)
  54.       [((variant v ds₀) (variant v ds₁))
  55.        (for/b∧ ([d₀ (in-vector ds₀)]
  56.                 [d₁ (in-vector ds₁)])
  57.                (a/equal? d₀ d₁))]
  58.  
  59.       ;; Addresses are the same if they have cardinality 1. Distinct addresses don't overlap.
  60.       [((? Address-Egal?) (? Address-Egal?))
  61.        (egal-equal? d₀ d₁)]
  62.  
  63.       [((? Address-Structural? a₀) (? Address-Structural? a₁))
  64.        (if (eq? (egal-equal? a₀ a₁) #t)
  65.            #t
  66.            ;; INVARIANT: not possible to be -unmapped since there must be
  67.            ;; at least one value mapped in a store's address.
  68.            (for*/bδ ([d₀ (in-set (store-ref store-spaces a₀))]
  69.                      [d₁ (in-set (store-ref store-spaces a₁))])
  70.                     (a/equal? d₀ d₁)))]
  71.  
  72.       [((? dict? m₀) (? dict? m₁)) (concrete-ffun-equal? m₀ m₁)]
  73.  
  74.       ;; If at least one map has qualification, we can check the other with the expectation of the same.
  75.       ;; We log the incident for future debugging, since it seems like we shouldn't get this far.
  76.       [((? dict? m₀) (abstract-ffun m₁))
  77.        (log-info (format "Qualified/unqualified dictionary equality check ~a ~a" d₀ d₁))
  78.        (ffun-equal? m₀ m₁)]
  79.       [((abstract-ffun m₀) (? dict? m₁))
  80.        (log-info (format "Qualified/unqualified dictionary equality check ~a ~a" d₀ d₁))
  81.        (ffun-equal? m₀ m₁)]
  82.       [((abstract-ffun m₀) (abstract-ffun m₁)) (ffun-equal? m₀ m₁)]
  83.       ;; Discrete cases
  84.       [((discrete-ffun m₀) (? dict? m₁))
  85.        (log-info (format "Qualified/unqualified (discrete) dictionary equality check ~a ~a" d₀ d₁))
  86.        (discrete-ffun-equal? m₀ m₁)]
  87.       [((? dict? m₀) (discrete-ffun m₁))
  88.        (log-info (format "Qualified/unqualified (discrete) dictionary equality check ~a ~a" d₀ d₁))
  89.        (discrete-ffun-equal? m₀ m₁)]
  90.       [((discrete-ffun m₀) (discrete-ffun m₁))
  91.        (discrete-ffun-equal? m₀ m₁)]
  92.  
  93.       ;; OPT-OP: This has no information on discrete abstractions, thus n²logn instead of sometimes nlogn
  94.       [((? set? s₀) (? set? s₁))
  95.        (define (⊆? s₀ s₁)
  96.          (for/b∧ ([v (in-set s₀)])
  97.                  (for/b∨ ([v* (in-set s₁)])
  98.                          (a/equal? v v*))))
  99.        (b∧ (⊆? s₀ s₁) (⊆? s₁ s₀))]
  100.  
  101.       [(atom atom) #t]
  102.  
  103.       [((external ex v₀) (external ex v₁))
  104.        (match-define (External-Space _ card precision special-equality) ex)
  105.        (if special-equality
  106.            (special-equality v₀ v₁ μ #;a/equal?)
  107.            (match precision
  108.              ['concrete (equal? v₀ v₁)]
  109.              ['discrete-abstraction (b∧ (equal? v₀ v₁) (implies (eq? (card v₀ μ)) 'b.⊤))]
  110.              ['abstract (error 'a/match "Cannot have non-discrete abstraction of external values without a custom equality relation ~a" d₀)]))]
  111.       [(_ _) #f]))
  112.  
  113.   ;; Circular addresses are possible
  114.   ;; OPT-OP?: Racket impl of equal? uses union-find instead of Map[_,Set[_]].
  115.   ;;          Is that applicable here?
  116.   (define seen (make-hasheq))
  117.   (define (a/equal? d₀ d₁)
  118.     (define checked-against (hash-ref! seen d₀ mutable-seteq))
  119.     ;; already checked  assume equal
  120.     ;; XXX: should this be #t or 'b.⊤?
  121.     (or (set-member? checked-against d₁)
  122.         (begin (set-add! checked-against d₁)
  123.                (equal-step d₀ d₁))))
  124.  
  125.   (a/equal? d₀ d₁))

=>

eval:2:0: match: syntax error in pattern

  in: (Address-Egal space a)