1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-25 08:12:11 -07:00

Support more kinds of hashtable via make-hashtable.

Fix bug in eqv (character objects now test equal if they represent the same character).

Copied from Perforce
 Change: 180284
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2012-11-02 16:02:05 +00:00
parent 4922259f66
commit ef98f2a9c6
2 changed files with 49 additions and 10 deletions

View file

@ -585,18 +585,30 @@ static int eqp(obj_t obj1, obj_t obj2)
static unsigned long eqv_hash(obj_t obj)
{
if(TYPE(obj) == TYPE_INTEGER)
switch(TYPE(obj)) {
case TYPE_INTEGER:
return obj->integer.integer;
else
case TYPE_CHARACTER:
return obj->character.c;
default:
return eq_hash(obj);
}
}
static int eqvp(obj_t obj1, obj_t obj2)
{
return obj1 == obj2 ||
(TYPE(obj1) == TYPE_INTEGER &&
TYPE(obj2) == TYPE_INTEGER &&
obj1->integer.integer == obj2->integer.integer);
if (obj1 == obj2)
return 1;
if (TYPE(obj1) != TYPE(obj2))
return 0;
switch(TYPE(obj1)) {
case TYPE_INTEGER:
return obj1->integer.integer == obj2->integer.integer;
case TYPE_CHARACTER:
return obj1->character.c == obj2->character.c;
default:
return 0;
}
}
static unsigned long string_hash(obj_t obj)
@ -2924,6 +2936,22 @@ static obj_t entry_string_hash(obj_t env, obj_t op_env, obj_t operator, obj_t op
}
static obj_t entry_eq_hash(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
eval_args(operator->operator.name, env, op_env, operands, 1, &arg);
return make_integer(eq_hash(arg));
}
static obj_t entry_eqv_hash(obj_t env, obj_t op_env, obj_t operator, obj_t operands)
{
obj_t arg;
eval_args(operator->operator.name, env, op_env, operands, 1, &arg);
return make_integer(eqv_hash(arg));
}
static obj_t make_hashtable(obj_t operator, obj_t rest, hash_t hashf, cmp_t cmpf)
{
size_t length;
@ -2996,10 +3024,17 @@ static obj_t entry_make_hashtable(obj_t env, obj_t op_env, obj_t operator, obj_t
error("%s: first argument must be a procedure", operator->operator.name);
unless(TYPE(cmpf) == TYPE_OPERATOR)
error("%s: first argument must be a procedure", operator->operator.name);
unless(hashf->operator.entry == entry_string_hash
&& cmpf->operator.entry == entry_string_equalp)
error("%s: arguments not supported", operator->operator.name);
return make_hashtable(operator, rest, string_hash, string_equalp);
if (hashf->operator.entry == entry_eq_hash
&& cmpf->operator.entry == entry_eqp)
return make_hashtable(operator, rest, eq_hash, eqp);
if (hashf->operator.entry == entry_eqv_hash
&& cmpf->operator.entry == entry_eqvp)
return make_hashtable(operator, rest, eqv_hash, eqvp);
if (hashf->operator.entry == entry_string_hash
&& cmpf->operator.entry == entry_string_equalp)
return make_hashtable(operator, rest, string_hash, string_equalp);
error("%s: arguments not supported", operator->operator.name);
return obj_undefined;
}
@ -3248,6 +3283,8 @@ static struct {char *name; entry_t entry;} funtab[] = {
{"hashtable-contains?", entry_hashtable_containsp},
{"hashtable-keys", entry_hashtable_keys},
{"string-hash", entry_string_hash},
{"eq-hash", entry_eq_hash},
{"eqv-hash", entry_eqv_hash},
};

View file

@ -47,8 +47,10 @@
(check '(ht-test (make-hashtable string-hash string=?) stringify) #t)
(define (symbolize n) (string->symbol (make-string n #\a)))
(check '(ht-test (make-eq-hashtable) symbolize) #t)
(check '(ht-test (make-hashtable eq-hash eq?) symbolize) #t)
(define (identity n) n)
(check '(ht-test (make-eqv-hashtable) identity) #t)
(check '(ht-test (make-hashtable eqv-hash eqv?) identity) #t)
(write-string "All tests pass.")
(newline)