Skip to content

Commit f548137

Browse files
committed
Move most of the equality tests into their own file
1 parent f67f696 commit f548137

File tree

3 files changed

+71
-65
lines changed

3 files changed

+71
-65
lines changed

airship-scheme.asd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
:zr-utils)
2020
:components ((:file "package")
2121
(:file "scheme-boolean")
22+
(:file "scheme-core")
2223
(:file "scheme-types")
2324
(:file "scheme-string")
24-
(:file "scheme-core")
25+
(:file "equality")
2526
(:file "scheme-write")
2627
(:file "scheme-read")
2728
(:file "standard-procedures")))

equality.lisp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
;;;; -*- mode: common-lisp; -*-
2+
3+
;;;; Non-string equality testing
4+
5+
(in-package #:airship-scheme)
6+
7+
(define-function (%symbol= :inline t :check-type t) ((symbol-1 symbol) (symbol-2 symbol))
8+
(eq symbol-1 symbol-2))
9+
10+
(defun symbol= (&rest symbols)
11+
"Tests if one or more symbols are equal to each other"
12+
(compare #'%symbol= symbols))
13+
14+
(defun eqv? (x y)
15+
"
16+
Tests if two objects are Scheme-equivalent to each other, using the
17+
rules provided in the r7rs-small specification.
18+
"
19+
(typecase x
20+
(symbol (typecase y (symbol (%symbol= x y))))
21+
(inexact? (typecase y (inexact? (= x y))))
22+
(exact? (typecase y (exact? (= x y))))
23+
(character (typecase y (character (char= x y))))
24+
(t (eq x y))))
25+
26+
;;; TODO: If circular and equal?, then this iterates too much because
27+
;;; it goes to the first detected part of the cycle rather than to the
28+
;;; start of it. It can't just stop at the detection of the cycle
29+
;;; because of e.g. '(-1 0 . #1=(1 2 3 4 5 6 7 8 9 . #1#))
30+
(define-function list-equal? ((list1 list) (list2 list))
31+
;; Note: Tested in a more verbose way so that the list lengths match
32+
;; in the ALWAYS test and so lists with cycles always terminate.
33+
(loop :with end? := nil
34+
:with cycle-x := nil
35+
:with cycle-y := nil
36+
:for x := list1 :then (cdr x)
37+
:for y := list2 :then (cdr y)
38+
;; For cycle testing to ensure termination
39+
:for x-fast := list1 :then (cddr x-fast)
40+
:for y-fast := list2 :then (cddr y-fast)
41+
:for i :from 0
42+
:until end?
43+
;; Recursive equality test
44+
:always (or (and (endp x) (endp y))
45+
(equal? (car x) (car y)))
46+
:do
47+
;; End test
48+
(when (or (endp x) (endp y) (eq x cycle-x) (eq y cycle-y))
49+
(setf end? t))
50+
;; Cycle tests
51+
(when (plusp i)
52+
(when (and x-fast (not cycle-x) (eq x x-fast))
53+
(setf cycle-x x))
54+
(when (and y-fast (not cycle-y) (eq y y-fast))
55+
(setf cycle-y y)))))
56+
57+
(defun vector-equal? (x y)
58+
(and (typep y (type-of x))
59+
(= (length x) (length y))
60+
(loop :for a :across x
61+
:for b :across y
62+
:always (equal? a b))))
63+
64+
;;; TODO: use a sequence-generic comparison when extensible-sequences is used
65+
(defun equal? (x y)
66+
(typecase x
67+
(list (and (listp y) (list-equal? x y)))
68+
(vector (and (vectorp y) (vector-equal? x y)))
69+
(t (eqv? x y))))

scheme-core.lisp

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,6 @@ in a form that CL expects.
4343
"Interns a Scheme symbol using one package, with its case inverted."
4444
(intern (invert-case string) '#:r7rs))
4545

46-
(define-function (%symbol= :inline t :check-type t) ((symbol-1 symbol) (symbol-2 symbol))
47-
(eq symbol-1 symbol-2))
48-
49-
(defun symbol= (&rest symbols)
50-
"Tests if one or more symbols are equal to each other"
51-
(compare #'%symbol= symbols))
52-
5346
(define-function (nanp :inline t) ((number number))
5447
"Tests if a number is NaN"
5548
(and (floatp number) (f:float-nan-p number)))
@@ -62,63 +55,6 @@ in a form that CL expects.
6255
"Tests if a number is both not NaN and not an infinity"
6356
(not (and (floatp number) (or (infinitep number) (nanp number)))))
6457

65-
(defun eqv? (x y)
66-
"
67-
Tests if two objects are Scheme-equivalent to each other, using the
68-
rules provided in the r7rs-small specification.
69-
"
70-
(typecase x
71-
(symbol (typecase y (symbol (%symbol= x y))))
72-
(inexact? (typecase y (inexact? (= x y))))
73-
(exact? (typecase y (exact? (= x y))))
74-
(character (typecase y (character (char= x y))))
75-
(t (eq x y))))
76-
77-
;;; TODO: If circular and equal?, then this iterates too much because
78-
;;; it goes to the first detected part of the cycle rather than to the
79-
;;; start of it. It can't just stop at the detection of the cycle
80-
;;; because of e.g. '(-1 0 . #1=(1 2 3 4 5 6 7 8 9 . #1#))
81-
(define-function list-equal? ((list1 list) (list2 list))
82-
;; Note: Tested in a more verbose way so that the list lengths match
83-
;; in the ALWAYS test and so lists with cycles always terminate.
84-
(loop :with end? := nil
85-
:with cycle-x := nil
86-
:with cycle-y := nil
87-
:for x := list1 :then (cdr x)
88-
:for y := list2 :then (cdr y)
89-
;; For cycle testing to ensure termination
90-
:for x-fast := list1 :then (cddr x-fast)
91-
:for y-fast := list2 :then (cddr y-fast)
92-
:for i :from 0
93-
:until end?
94-
;; Recursive equality test
95-
:always (or (and (endp x) (endp y))
96-
(equal? (car x) (car y)))
97-
:do
98-
;; End test
99-
(when (or (endp x) (endp y) (eq x cycle-x) (eq y cycle-y))
100-
(setf end? t))
101-
;; Cycle tests
102-
(when (plusp i)
103-
(when (and x-fast (not cycle-x) (eq x x-fast))
104-
(setf cycle-x x))
105-
(when (and y-fast (not cycle-y) (eq y y-fast))
106-
(setf cycle-y y)))))
107-
108-
(defun vector-equal? (x y)
109-
(and (typep y (type-of x))
110-
(= (length x) (length y))
111-
(loop :for a :across x
112-
:for b :across y
113-
:always (equal? a b))))
114-
115-
;;; TODO: use a sequence-generic comparison when extensible-sequences is used
116-
(defun equal? (x y)
117-
(typecase x
118-
(list (and (listp y) (list-equal? x y)))
119-
(vector (and (vectorp y) (vector-equal? x y)))
120-
(t (eqv? x y))))
121-
12258
(defun coerce-subseq (sequence result-type &optional start end)
12359
"Coerces a subsequence into the result type"
12460
(let ((subseq (if start

0 commit comments

Comments
 (0)