match.scm 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. ;;; Simple pattern-matcher
  2. ;;; Copyright (C) 2024 Igalia, S.L.
  3. ;;;
  4. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  5. ;;; you may not use this file except in compliance with the License.
  6. ;;; You may obtain a copy of the License at
  7. ;;;
  8. ;;; http://www.apache.org/licenses/LICENSE-2.0
  9. ;;;
  10. ;;; Unless required by applicable law or agreed to in writing, software
  11. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  12. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ;;; See the License for the specific language governing permissions and
  14. ;;; limitations under the License.
  15. ;;; Commentary:
  16. ;;;
  17. ;;; Simple pattern matcher, based on Oleg Kiselyov's pmatch.
  18. ;;;
  19. ;;; Code:
  20. (library (hoot match)
  21. (export match)
  22. (import (hoot primitives)
  23. (hoot errors))
  24. (define (vector-ref v n) (%vector-ref v n))
  25. (define (null? x) (%null? x))
  26. (define (eq? x y) (%eq? x y))
  27. (define (1+ x) (%+ x 1))
  28. (define (vector? x) (%vector? x))
  29. (define (pair? x) (%pair? x))
  30. (define (car x) (%car x))
  31. (define (cdr x) (%cdr x))
  32. (define (vector-length x) (%vector-length x))
  33. (define (length x)
  34. (if (null? x)
  35. 0
  36. (1+ (length (cdr x)))))
  37. (define-syntax-rule (simple-match e cs ...)
  38. (let ((v e)) (simple-match-1 v cs ...)))
  39. (define-syntax simple-match-1
  40. (syntax-rules ()
  41. ((_ v) (raise (make-match-error v)))
  42. ((_ v (pat e0 e ...) cs ...)
  43. (let ((fk (lambda () (simple-match-1 v cs ...))))
  44. (simple-match-pat v pat (let () e0 e ...) (fk))))))
  45. (define-syntax simple-match-patv
  46. (syntax-rules ()
  47. ((_ v idx () kt kf) kt)
  48. ((_ v idx (x . y) kt kf)
  49. (simple-match-pat (vector-ref v idx) x
  50. (simple-match-patv v (1+ idx) y kt kf)
  51. kf))))
  52. (define-syntax simple-match-pat
  53. (syntax-rules (_ quote unquote ? and or not)
  54. ((_ v _ kt kf) kt)
  55. ((_ v () kt kf) (if (null? v) kt kf))
  56. ((_ v #t kt kf) (if (eq? v #t) kt kf))
  57. ((_ v #f kt kf) (if (eq? v #f) kt kf))
  58. ((_ v (and) kt kf) kt)
  59. ((_ v (and x . y) kt kf)
  60. (simple-match-pat v x (simple-match-pat v (and . y) kt kf) kf))
  61. ((_ v (or) kt kf) kf)
  62. ((_ v (or x . y) kt kf)
  63. (let ((tk (lambda () kt)))
  64. (simple-match-pat v x (tk) (simple-match-pat v (or . y) (tk) kf))))
  65. ((_ v (not pat) kt kf) (simple-match-pat v pat kf kt))
  66. ((_ v (quote lit) kt kf)
  67. (if (eq? v (quote lit)) kt kf))
  68. ((_ v (? proc) kt kf) (simple-match-pat v (? proc _) kt kf))
  69. ((_ v (? proc pat) kt kf)
  70. (if (proc v) (simple-match-pat v pat kt kf) kf))
  71. ((_ v (x . y) kt kf)
  72. (if (pair? v)
  73. (let ((vx (car v)) (vy (cdr v)))
  74. (simple-match-pat vx x (simple-match-pat vy y kt kf) kf))
  75. kf))
  76. ((_ v #(x ...) kt kf)
  77. (if (and (vector? v)
  78. (eq? (vector-length v) (length '(x ...))))
  79. (simple-match-patv v 0 (x ...) kt kf)
  80. kf))
  81. ((_ v var kt kf) (let ((var v)) kt))))
  82. (define-syntax-rule (match e cs ...) (simple-match e cs ...)))