103 lines
2.0 KiB
C
103 lines
2.0 KiB
C
|
/*
|
||
|
* $Id: symbol.c,v 1.3 2007/04/30 08:32:41 bacon Exp $
|
||
|
*/
|
||
|
|
||
|
#include <ase/stx/symbol.h>
|
||
|
#include <ase/stx/object.h>
|
||
|
#include <ase/stx/misc.h>
|
||
|
|
||
|
static void __grow_symtab (ase_stx_t* stx)
|
||
|
{
|
||
|
ase_word_t capa, ncapa, i, j;
|
||
|
ase_word_t* nspace;
|
||
|
|
||
|
capa = stx->symtab.capacity;
|
||
|
ncapa = capa << 1;
|
||
|
|
||
|
nspace = (ase_word_t*)ase_malloc(ase_sizeof(ase_word_t) * ncapa);
|
||
|
if (nspace == ASE_NULL)
|
||
|
{
|
||
|
/* TODO: handle memory error */
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < capa; i++)
|
||
|
{
|
||
|
ase_word_t x = stx->symtab.datum[i];
|
||
|
if (x == stx->nil) continue;
|
||
|
|
||
|
j = ase_stx_strxhash (
|
||
|
ASE_STX_DATA(stx,x), ASE_STX_SIZE(stx,x)) % ncapa;
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
if (nspace[j] == stx->nil)
|
||
|
{
|
||
|
nspace[j] = x;
|
||
|
break;
|
||
|
}
|
||
|
j = (j % ncapa) + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
stx->symtab.capacity = ncapa;
|
||
|
ase_free (stx->symtab.datum);
|
||
|
stx->symtab.datum = nspace;
|
||
|
}
|
||
|
|
||
|
ase_word_t ase_stx_new_symbol (ase_stx_t* stx, const ase_char_t* name)
|
||
|
{
|
||
|
return ase_stx_new_symbolx (stx, name, ase_strlen(name));
|
||
|
}
|
||
|
|
||
|
ase_word_t ase_stx_new_symbolx (
|
||
|
ase_stx_t* stx, const ase_char_t* name, ase_word_t len)
|
||
|
{
|
||
|
ase_word_t capa, hash, index, size, x;
|
||
|
|
||
|
capa = stx->symtab.capacity;
|
||
|
size = stx->symtab.size;
|
||
|
|
||
|
if (capa <= size + 1)
|
||
|
{
|
||
|
__grow_symtab (stx);
|
||
|
capa = stx->symtab.capacity;
|
||
|
}
|
||
|
|
||
|
hash = ase_stx_strxhash(name,len);
|
||
|
index = hash % stx->symtab.capacity;
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
x = stx->symtab.datum[index];
|
||
|
if (x == stx->nil)
|
||
|
{
|
||
|
/* insert a new item into an empty slot */
|
||
|
x = ase_stx_alloc_char_objectx (stx, name, len);
|
||
|
ASE_STX_CLASS(stx,x) = stx->class_symbol;
|
||
|
stx->symtab.datum[index] = x;
|
||
|
stx->symtab.size++;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (ase_strxncmp(name, len,
|
||
|
ASE_STX_DATA(stx,x), ASE_STX_SIZE(stx,x)) == 0) break;
|
||
|
|
||
|
index = (index % stx->symtab.capacity) + 1;
|
||
|
}
|
||
|
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
void ase_stx_traverse_symbol_table (
|
||
|
ase_stx_t* stx, void (*func) (ase_stx_t*,ase_word_t,void*), void* data)
|
||
|
{
|
||
|
ase_word_t index, x;
|
||
|
|
||
|
for (index = 0; index < stx->symtab.capacity; index++)
|
||
|
{
|
||
|
x = stx->symtab.datum[index];
|
||
|
if (x != stx->nil) func (stx, x, data);
|
||
|
}
|
||
|
}
|
||
|
|