mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-20 22:29:16 +02:00
adding equal?/bounded and an optimized equiv? which uses it
This commit is contained in:
parent
1edfa35ad8
commit
89f5d9ea65
5 changed files with 70 additions and 8 deletions
|
@ -1047,6 +1047,7 @@ SEXP_API sexp sexp_alloc_tagged_aux(sexp ctx, size_t size, sexp_uint_t tag sexp_
|
||||||
SEXP_API sexp sexp_make_context(sexp ctx, size_t size, size_t max_size);
|
SEXP_API sexp sexp_make_context(sexp ctx, size_t size, size_t max_size);
|
||||||
SEXP_API sexp sexp_cons_op(sexp ctx sexp_api_params(self, n), sexp head, sexp tail);
|
SEXP_API sexp sexp_cons_op(sexp ctx sexp_api_params(self, n), sexp head, sexp tail);
|
||||||
SEXP_API sexp sexp_list2(sexp ctx, sexp a, sexp b);
|
SEXP_API sexp sexp_list2(sexp ctx, sexp a, sexp b);
|
||||||
|
SEXP_API sexp sexp_equalp_bound (sexp ctx sexp_api_params(self, n), sexp a, sexp b, sexp bound);
|
||||||
SEXP_API sexp sexp_equalp_op (sexp ctx sexp_api_params(self, n), sexp a, sexp b);
|
SEXP_API sexp sexp_equalp_op (sexp ctx sexp_api_params(self, n), sexp a, sexp b);
|
||||||
SEXP_API sexp sexp_listp_op(sexp ctx sexp_api_params(self, n), sexp obj);
|
SEXP_API sexp sexp_listp_op(sexp ctx sexp_api_params(self, n), sexp obj);
|
||||||
SEXP_API sexp sexp_reverse_op(sexp ctx sexp_api_params(self, n), sexp ls);
|
SEXP_API sexp sexp_reverse_op(sexp ctx sexp_api_params(self, n), sexp ls);
|
||||||
|
|
6
lib/chibi/equiv.module
Normal file
6
lib/chibi/equiv.module
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
(define-module (chibi equiv)
|
||||||
|
(export equiv?)
|
||||||
|
(import-immutable (scheme))
|
||||||
|
(import (srfi 69))
|
||||||
|
(include "equiv.scm"))
|
44
lib/chibi/equiv.scm
Normal file
44
lib/chibi/equiv.scm
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
|
||||||
|
(define (equiv? a b)
|
||||||
|
(let ((equivs (make-hash-table eq?)))
|
||||||
|
(define (get-equivs x)
|
||||||
|
(or (hash-table-ref/default equivs x #f)
|
||||||
|
(let ((tmp (make-hash-table eq?)))
|
||||||
|
(hash-table-set! equivs x tmp)
|
||||||
|
tmp)))
|
||||||
|
(define (merge! tab x)
|
||||||
|
(hash-table-set! tab x tab)
|
||||||
|
(cond ((hash-table-ref/default equivs x #f)
|
||||||
|
=> (lambda (tab2)
|
||||||
|
(hash-table-walk tab2 (lambda (key value)
|
||||||
|
(hash-table-set! tab key tab)))))))
|
||||||
|
(define (equiv? a b)
|
||||||
|
(cond
|
||||||
|
((eq? a b))
|
||||||
|
((pair? a)
|
||||||
|
(and (pair? b)
|
||||||
|
(let ((a-tab (get-equivs a)))
|
||||||
|
(hash-table-ref
|
||||||
|
a-tab
|
||||||
|
b
|
||||||
|
(lambda ()
|
||||||
|
(merge! a-tab b)
|
||||||
|
(and (equiv? (car a) (car b))
|
||||||
|
(equiv? (cdr a) (cdr b))))))))
|
||||||
|
((vector? a)
|
||||||
|
(and (vector? b)
|
||||||
|
(= (vector-length a) (vector-length b))
|
||||||
|
(let ((a-tab (get-equivs a)))
|
||||||
|
(hash-table-ref
|
||||||
|
a-tab
|
||||||
|
b
|
||||||
|
(lambda ()
|
||||||
|
(merge! a-tab b)
|
||||||
|
(let lp ((i (- (vector-length a) 1)))
|
||||||
|
(or (< i 0)
|
||||||
|
(and (equiv? (vector-ref a i) (vector-ref b i))
|
||||||
|
(lp (- i 1))))))))))
|
||||||
|
(else
|
||||||
|
(equal? a b))))
|
||||||
|
(let ((res (equal?/bounded a b 1000000)))
|
||||||
|
(and res (or (> res 0) (equiv? a b)) #t))))
|
|
@ -96,6 +96,7 @@ _FN2OPTP(SEXP_VOID,_I(SEXP_OBJECT), _I(SEXP_OPORT), "write", (sexp)"current-outp
|
||||||
_FN2OPTP(SEXP_VOID, _I(SEXP_OBJECT), _I(SEXP_OPORT), "display", (sexp)"current-output-port", sexp_display_op),
|
_FN2OPTP(SEXP_VOID, _I(SEXP_OBJECT), _I(SEXP_OPORT), "display", (sexp)"current-output-port", sexp_display_op),
|
||||||
_FN1OPTP(SEXP_VOID, _I(SEXP_OPORT), "flush-output", (sexp)"current-output-port", sexp_flush_output_op),
|
_FN1OPTP(SEXP_VOID, _I(SEXP_OPORT), "flush-output", (sexp)"current-output-port", sexp_flush_output_op),
|
||||||
_FN2(_I(SEXP_BOOLEAN), _I(SEXP_OBJECT), _I(SEXP_OBJECT), "equal?", 0, sexp_equalp_op),
|
_FN2(_I(SEXP_BOOLEAN), _I(SEXP_OBJECT), _I(SEXP_OBJECT), "equal?", 0, sexp_equalp_op),
|
||||||
|
_FN3(_I(SEXP_BOOLEAN), _I(SEXP_OBJECT), _I(SEXP_OBJECT), _I(SEXP_OBJECT), "equal?/bounded", 0, sexp_equalp_bound),
|
||||||
_FN1(_I(SEXP_BOOLEAN), _I(SEXP_OBJECT), "list?", 0, sexp_listp_op),
|
_FN1(_I(SEXP_BOOLEAN), _I(SEXP_OBJECT), "list?", 0, sexp_listp_op),
|
||||||
_FN1(_I(SEXP_BOOLEAN), _I(SEXP_OBJECT), "identifier?", 0, sexp_identifierp_op),
|
_FN1(_I(SEXP_BOOLEAN), _I(SEXP_OBJECT), "identifier?", 0, sexp_identifierp_op),
|
||||||
_FN1(_I(SEXP_SYMBOL), _I(SEXP_OBJECT), "identifier->symbol", 0, sexp_syntactic_closure_expr_op),
|
_FN1(_I(SEXP_SYMBOL), _I(SEXP_OBJECT), "identifier->symbol", 0, sexp_syntactic_closure_expr_op),
|
||||||
|
|
26
sexp.c
26
sexp.c
|
@ -654,7 +654,7 @@ sexp sexp_length_op (sexp ctx sexp_api_params(self, n), sexp ls1) {
|
||||||
return sexp_make_fixnum(res + (sexp_pairp(ls2) ? 1 : 0));
|
return sexp_make_fixnum(res + (sexp_pairp(ls2) ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
sexp sexp_equalp_op (sexp ctx sexp_api_params(self, n), sexp a, sexp b) {
|
sexp sexp_equalp_bound (sexp ctx sexp_api_params(self, n), sexp a, sexp b, sexp bound) {
|
||||||
sexp_uint_t size;
|
sexp_uint_t size;
|
||||||
sexp_sint_t i, len;
|
sexp_sint_t i, len;
|
||||||
sexp t, *p, *q;
|
sexp t, *p, *q;
|
||||||
|
@ -662,7 +662,7 @@ sexp sexp_equalp_op (sexp ctx sexp_api_params(self, n), sexp a, sexp b) {
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
if (a == b)
|
if (a == b)
|
||||||
return SEXP_TRUE;
|
return bound;
|
||||||
else if ((! sexp_pointerp(a)) || (! sexp_pointerp(b))
|
else if ((! sexp_pointerp(a)) || (! sexp_pointerp(b))
|
||||||
|| (sexp_pointer_tag(a) != sexp_pointer_tag(b)))
|
|| (sexp_pointer_tag(a) != sexp_pointer_tag(b)))
|
||||||
return SEXP_FALSE;
|
return SEXP_FALSE;
|
||||||
|
@ -670,12 +670,15 @@ sexp sexp_equalp_op (sexp ctx sexp_api_params(self, n), sexp a, sexp b) {
|
||||||
/* a and b are both pointers of the same type */
|
/* a and b are both pointers of the same type */
|
||||||
#if SEXP_USE_BIGNUMS
|
#if SEXP_USE_BIGNUMS
|
||||||
if (sexp_pointer_tag(a) == SEXP_BIGNUM)
|
if (sexp_pointer_tag(a) == SEXP_BIGNUM)
|
||||||
return sexp_make_boolean(!sexp_bignum_compare(a, b));
|
return !sexp_bignum_compare(a, b) ? bound : SEXP_FALSE;
|
||||||
#endif
|
#endif
|
||||||
#if SEXP_USE_FLONUMS && ! SEXP_USE_IMMEDIATE_FLONUMS
|
#if SEXP_USE_FLONUMS && ! SEXP_USE_IMMEDIATE_FLONUMS
|
||||||
if (sexp_pointer_tag(a) == SEXP_FLONUM)
|
if (sexp_pointer_tag(a) == SEXP_FLONUM)
|
||||||
return sexp_make_boolean(sexp_flonum_value(a) == sexp_flonum_value(b));
|
return (sexp_flonum_value(a) == sexp_flonum_value(b)) ? bound : SEXP_FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
if (sexp_unbox_fixnum(bound) < 0)
|
||||||
|
return bound;
|
||||||
|
bound = sexp_fx_sub(bound, SEXP_ONE);
|
||||||
t = sexp_object_type(ctx, a);
|
t = sexp_object_type(ctx, a);
|
||||||
p0 = ((char*)a) + offsetof(struct sexp_struct, value);
|
p0 = ((char*)a) + offsetof(struct sexp_struct, value);
|
||||||
p = (sexp*) (((char*)a) + sexp_type_field_base(t));
|
p = (sexp*) (((char*)a) + sexp_type_field_base(t));
|
||||||
|
@ -698,13 +701,20 @@ sexp sexp_equalp_op (sexp ctx sexp_api_params(self, n), sexp a, sexp b) {
|
||||||
/* check eq-object slots */
|
/* check eq-object slots */
|
||||||
len = sexp_type_num_eq_slots_of_object(t, a);
|
len = sexp_type_num_eq_slots_of_object(t, a);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
for (i=0; i<len-1; i++)
|
for (i=0; i<len-1; i++) {
|
||||||
if (p[i] != q[i] && sexp_not(sexp_equalp(ctx, p[i], q[i])))
|
bound = sexp_equalp_bound(ctx sexp_api_pass(self, n), p[i], q[i], bound);
|
||||||
return SEXP_FALSE;
|
if (sexp_not(bound)) return SEXP_FALSE;
|
||||||
|
}
|
||||||
/* tail-recurse on the last value */
|
/* tail-recurse on the last value */
|
||||||
a = p[len-1]; b = q[len-1]; goto loop;
|
a = p[len-1]; b = q[len-1]; goto loop;
|
||||||
}
|
}
|
||||||
return SEXP_TRUE;
|
return bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
sexp sexp_equalp_op (sexp ctx sexp_api_params(self, n), sexp a, sexp b) {
|
||||||
|
return sexp_make_boolean(
|
||||||
|
sexp_truep(sexp_equalp_bound(ctx sexp_api_pass(self, n), a, b,
|
||||||
|
sexp_make_fixnum(1000000000))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************* strings, symbols, vectors **********************/
|
/********************* strings, symbols, vectors **********************/
|
||||||
|
|
Loading…
Add table
Reference in a new issue