added more code for symbol table and system dictionary
This commit is contained in:
parent
143bf5aa2b
commit
3cc4595018
@ -44,57 +44,6 @@ static qse_word_t new_assoc (
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
static qse_word_t find_slot (
|
|
||||||
qse_stx_t* stx, qse_word_t dic, qse_word_t key)
|
|
||||||
{
|
|
||||||
qse_word_t size, hash, index, assoc, sym;
|
|
||||||
qse_stx_dic_t* ptr;
|
|
||||||
|
|
||||||
/* ensure that dic is a system dictionary */
|
|
||||||
QSE_ASSERT (REFISIDX(stx,dic));
|
|
||||||
QSE_ASSERT (OBJTYPE(stx,dic) == WORDOBJ);
|
|
||||||
QSE_ASSERT (dic == stx->ref.sysdic ||
|
|
||||||
OBJCLASS(stx,key) == stx->ref.class_system_dictionary);
|
|
||||||
|
|
||||||
/* ensure that the key is a symbol */
|
|
||||||
QSE_ASSERT (REFISIDX(stx,key));
|
|
||||||
QSE_ASSERT (OBJCLASS(stx,key) == stx->ref.class_symbol);
|
|
||||||
QSE_ASSERT (OBJTYPE(stx,key) == CHAROBJ);
|
|
||||||
|
|
||||||
size = OBJSIZE (stx, dic);
|
|
||||||
hash = qse_stx_hashobj (stx, key);
|
|
||||||
|
|
||||||
/* consider tally, the only instance variable of a system dicionary */
|
|
||||||
index = hash % (size - 1);
|
|
||||||
|
|
||||||
ptr = (qse_stx_dic_t*) REFTOIDX (stx, dic);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
assoc = ptr->slot[index];
|
|
||||||
if (assoc == stx->ref.nil) break;
|
|
||||||
|
|
||||||
sym = WORDAT (stx, assoc, QSE_STX_ASSOC_KEY);
|
|
||||||
|
|
||||||
QSE_ASSERT (REFISIDX(stx,sym));
|
|
||||||
QSE_ASSERT (OBJCLASS(stx,sym) == stx->ref.class_symbol);
|
|
||||||
QSE_ASSERT (OBJTYPE(stx,sym) == CHAROBJ);
|
|
||||||
|
|
||||||
/* NOTE:
|
|
||||||
* shallow comparison is enough for identity check
|
|
||||||
* because a symbol can just be a key of a system dicionary
|
|
||||||
*/
|
|
||||||
if (qse_strxncmp(
|
|
||||||
&CHARAT(stx,key,0), OBJSIZE(stx,key),
|
|
||||||
&CHARAT(stx,key,0), OBJSIZE(stx,sym)) == 0) break;
|
|
||||||
|
|
||||||
/* consider tally here too */
|
|
||||||
index = index % (size - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qse_word_t grow_dic (qse_stx_t* stx, qse_word_t dic)
|
static qse_word_t grow_dic (qse_stx_t* stx, qse_word_t dic)
|
||||||
{
|
{
|
||||||
qse_word_t new, size, index, assoc;
|
qse_word_t new, size, index, assoc;
|
||||||
@ -117,7 +66,7 @@ static qse_word_t grow_dic (qse_stx_t* stx, qse_word_t dic)
|
|||||||
for (index = 1; index < size; index++)
|
for (index = 1; index < size; index++)
|
||||||
{
|
{
|
||||||
assoc = WORDAT(stx,dic,index);
|
assoc = WORDAT(stx,dic,index);
|
||||||
if (assoc == stx->nil) continue;
|
if (assoc == stx->ref.nil) continue;
|
||||||
|
|
||||||
qse_stx_putdic (stx, new,
|
qse_stx_putdic (stx, new,
|
||||||
WORDAT(stx,assoc,QSE_STX_ASSOC_KEY),
|
WORDAT(stx,assoc,QSE_STX_ASSOC_KEY),
|
||||||
@ -126,11 +75,11 @@ static qse_word_t grow_dic (qse_stx_t* stx, qse_word_t dic)
|
|||||||
|
|
||||||
/* TODO: explore if dic can be immediately destroyed. */
|
/* TODO: explore if dic can be immediately destroyed. */
|
||||||
|
|
||||||
QSE_ASSERT (qse_sizeof(qse_stx_object_t*) == qse_sizeof(qse_uint_t));
|
QSE_ASSERT (QSE_SIZEOF(qse_stx_object_t*) == QSE_SIZEOF(qse_uint_t));
|
||||||
|
|
||||||
QSE_SWAP (
|
QSE_SWAP (
|
||||||
QSE_STX_OBJPTR(stx,dic),
|
PTRBYIDX(stx,dic),
|
||||||
QSE_STX_OBJPTR(stx,new),
|
PTRBYIDX(stx,new),
|
||||||
qse_stx_object_t*,
|
qse_stx_object_t*,
|
||||||
qse_uint_t
|
qse_uint_t
|
||||||
);
|
);
|
||||||
@ -138,83 +87,151 @@ static qse_word_t grow_dic (qse_stx_t* stx, qse_word_t dic)
|
|||||||
return dic;
|
return dic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static qse_word_t find_slot (
|
||||||
|
qse_stx_t* stx, qse_word_t dic, qse_word_t key)
|
||||||
|
{
|
||||||
|
qse_word_t capa, hash;
|
||||||
|
qse_stx_dic_t* dicptr;
|
||||||
|
|
||||||
|
/* ensure that dic is a system dictionary */
|
||||||
|
QSE_ASSERT (REFISIDX(stx,dic));
|
||||||
|
QSE_ASSERT (OBJTYPE(stx,dic) == WORDOBJ);
|
||||||
|
QSE_ASSERT (dic == stx->ref.sysdic ||
|
||||||
|
OBJCLASS(stx,key) == stx->ref.class_system_dictionary);
|
||||||
|
|
||||||
|
/* ensure that the key is a symbol */
|
||||||
|
QSE_ASSERT (REFISIDX(stx,key));
|
||||||
|
QSE_ASSERT (OBJCLASS(stx,key) == stx->ref.class_symbol);
|
||||||
|
QSE_ASSERT (OBJTYPE(stx,key) == CHAROBJ);
|
||||||
|
|
||||||
|
capa = OBJSIZE(stx,dic) - 1; /* exclude the tally field */
|
||||||
|
hash = qse_stx_hashobj (stx, key) % capa;
|
||||||
|
|
||||||
|
dicptr = (qse_stx_dic_t*)PTRBYREF(stx,dic);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
qse_word_t assoc, sym;
|
||||||
|
|
||||||
|
assoc = dicptr->slot[hash];
|
||||||
|
if (assoc == stx->ref.nil) break; /* not found */
|
||||||
|
|
||||||
|
sym = WORDAT (stx, assoc, QSE_STX_ASSOC_KEY);
|
||||||
|
|
||||||
|
QSE_ASSERT (REFISIDX(stx,sym));
|
||||||
|
QSE_ASSERT (OBJCLASS(stx,sym) == stx->ref.class_symbol);
|
||||||
|
QSE_ASSERT (OBJTYPE(stx,sym) == CHAROBJ);
|
||||||
|
|
||||||
|
if (qse_strxncmp(
|
||||||
|
&CHARAT(stx,key,0), OBJSIZE(stx,key),
|
||||||
|
&CHARAT(stx,sym,0), OBJSIZE(stx,sym)) == 0) break;
|
||||||
|
|
||||||
|
hash = (hash + 1) % capa;
|
||||||
|
}
|
||||||
|
while (1);
|
||||||
|
|
||||||
|
/* Include the tally back when returning the association index.
|
||||||
|
* you can access the association with WORDAT() by using this index. */
|
||||||
|
return hash + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look up a system dictionary by a null-terminated string */
|
||||||
qse_word_t qse_stx_lookupdic (
|
qse_word_t qse_stx_lookupdic (
|
||||||
qse_stx_t* stx, qse_word_t dic, const qse_char_t* key)
|
qse_stx_t* stx, qse_word_t dic, const qse_char_t* skey)
|
||||||
{
|
{
|
||||||
qse_word_t size, hash, index, assoc, symbol;
|
qse_word_t capa, hash;
|
||||||
qse_stx_word_object_t* ptr;
|
qse_stx_dic_t* dicptr;
|
||||||
|
|
||||||
QSE_ASSERT (!QSE_STX_ISSMALLINT(dic) &&
|
QSE_ASSERT (REFISIDX(stx,dic));
|
||||||
QSE_STX_ISWORDOBJECT(stx, dic));
|
QSE_ASSERT (OBJTYPE(stx,dic) == WORDOBJ);
|
||||||
QSE_ASSERT (dic == stx->smalltalk ||
|
QSE_ASSERT (dic == stx->ref.sysdic ||
|
||||||
qse_stx_classof(stx,dic) == stx->class_system_dicionary);
|
OBJCLASS(stx,dic) == stx->ref.class_system_dictionary);
|
||||||
|
|
||||||
size = OBJSIZE(stx,dic);
|
capa = OBJSIZE(stx,dic) - 1; /* exclude the tally field */
|
||||||
hash = qse_stx_hash(key, qse_strlen(key) * qse_sizeof(qse_char_t));
|
hash = qse_stx_hashstr (stx, skey) % capa;
|
||||||
|
|
||||||
/* consider tally, the only instance variable of a system dicionary */
|
dicptr = (qse_stx_dic_t*)PTRBYREF(stx,dic);
|
||||||
index = hash % (size - 1);
|
|
||||||
|
|
||||||
ptr = QSE_STX_WORD_OBJECT(stx,dic);
|
do
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
{
|
||||||
assoc = ptr->slot[index];
|
qse_word_t assoc, keyref;
|
||||||
if (assoc == stx->ref.nil) break;
|
|
||||||
|
|
||||||
symbol = WORDAT(stx,assoc,QSE_STX_ASSOC_KEY);
|
assoc = dicptr->slot[hash];
|
||||||
QSE_ASSERT (qse_stx_classof(stx,symbol) == stx->class_symbol);
|
if (assoc == stx->ref.nil) break; /* not found */
|
||||||
|
|
||||||
|
keyref = WORDAT(stx,assoc,QSE_STX_ASSOC_KEY);
|
||||||
|
|
||||||
|
QSE_ASSERT (REFISIDX(stx,keyref));
|
||||||
|
QSE_ASSERT (OBJCLASS(stx,keyref) == stx->ref.class_symbol);
|
||||||
|
QSE_ASSERT (OBJTYPE(stx,keyref) == CHAROBJ);
|
||||||
|
|
||||||
if (qse_strxcmp (
|
if (qse_strxcmp (
|
||||||
QSE_STX_DATA(stx,symbol), OBJSIZE(stx,symbol), key) == 0) break;
|
&CHARAT(stx,keyref,0), OBJSIZE(stx,keyref),
|
||||||
|
skey) == 0) break;
|
||||||
|
|
||||||
/* consider tally here too */
|
hash = (hash + 1) % capa;
|
||||||
index = index % (size - 1);
|
}
|
||||||
|
while (1);
|
||||||
|
|
||||||
|
return dicptr->slot[hash];
|
||||||
}
|
}
|
||||||
|
|
||||||
return WORDAT(stx,dic,index);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
qse_word_t qse_stx_getdic (qse_stx_t* stx, qse_word_t dic, qse_word_t key)
|
qse_word_t qse_stx_getdic (qse_stx_t* stx, qse_word_t dic, qse_word_t key)
|
||||||
{
|
{
|
||||||
return WORDAT (stx, dic, find_slot (stx, dic, key));
|
return WORDAT (stx, dic, find_slot (stx, dic, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_word_t qse_stx_putdic (
|
qse_word_t qse_stx_putdic (
|
||||||
qse_stx_t* stx, qse_word_t dic, qse_word_t key, qse_word_t val)
|
qse_stx_t* stx, qse_word_t dic, qse_word_t key, qse_word_t value)
|
||||||
{
|
{
|
||||||
qse_word_t slot, capa, tally, assoc;
|
qse_word_t slot, capa, tally, assoc;
|
||||||
|
qse_stx_dic_t* dicptr;
|
||||||
|
|
||||||
/* the dicionary must have at least one slot excluding tally */
|
/* the dicionary must have at least one slot excluding tally */
|
||||||
QSE_ASSERT (OBJSIZE(stx,dic) > 1);
|
QSE_ASSERT (OBJSIZE(stx,dic) > 1);
|
||||||
|
|
||||||
capa = OBJSIZE(stx,dic) - 1;
|
capa = OBJSIZE(stx,dic) - 1;
|
||||||
tally = REFTOINT(WORDAT(stx,dic,0));
|
dicptr = (qse_stx_dic_t*)PTRBYREF(stx,dic);
|
||||||
if (capa <= tally + 1)
|
|
||||||
|
tally = REFTOINT(stx,WORDAT(stx,dic,QSE_STX_DIC_TALLY));
|
||||||
|
|
||||||
|
slot = find_slot (stx, dic, key);
|
||||||
|
assoc = WORDAT(stx,dic,slot);
|
||||||
|
|
||||||
|
if (assoc == stx->ref.nil)
|
||||||
{
|
{
|
||||||
|
/* the key is not found */
|
||||||
|
|
||||||
|
if (tally + 1 >= capa)
|
||||||
|
{
|
||||||
|
/* Enlarge the dictionary if there is one free slot left.
|
||||||
|
* The last free slot left is always maintained to be nil.
|
||||||
|
* The nil slot plays multiple roles.
|
||||||
|
* - make sure that lookup never enters a infinite loop.
|
||||||
|
* - the slot's index can be returned when no key is found.
|
||||||
|
*/
|
||||||
if (grow_dic (stx, dic) == stx->ref.nil) return stx->ref.nil;
|
if (grow_dic (stx, dic) == stx->ref.nil) return stx->ref.nil;
|
||||||
|
|
||||||
/* refresh tally */
|
/* refresh tally */
|
||||||
tally = REFTOINT(stx,WORDAT(stx,dic,QSE_STX_DIC_TALLY));
|
tally = REFTOINT(stx,WORDAT(stx,dic,QSE_STX_DIC_TALLY));
|
||||||
}
|
}
|
||||||
|
|
||||||
slot = find_slot (stx, dic, key);
|
|
||||||
|
|
||||||
assoc = WORDAT (stx, dic, slot);
|
|
||||||
if (assoc == stx->ref.nil)
|
|
||||||
{
|
|
||||||
assoc = new_assoc (stx, key, value);
|
assoc = new_assoc (stx, key, value);
|
||||||
if (assoc == stx->ref.nil) return stx->ref.nil;
|
if (assoc == stx->ref.nil) return stx->ref.nil;
|
||||||
|
|
||||||
WORDAT(stx,dic,slot) = assoc;
|
WORDAT(stx,dic,slot) = assoc;
|
||||||
WORDAT(stx,dic,QSE_STX_DIC_TALLY) = INTTOREF(stx,tally + 1);
|
WORDAT(stx,dic,QSE_STX_DIC_TALLY) = INTTOREF(stx,tally + 1);
|
||||||
}
|
}
|
||||||
else WORDAT (stx, assoc, QSE_STX_ASSOC_VALUE) = value;
|
else
|
||||||
|
{
|
||||||
return WORDAT(stx,dic,slot);
|
/* found the key. change the value */
|
||||||
|
WORDAT(stx,assoc,QSE_STX_ASSOC_VALUE) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
void qse_stx_walkdic (
|
void qse_stx_walkdic (
|
||||||
qse_stx_t* stx, qse_word_t dic,
|
qse_stx_t* stx, qse_word_t dic,
|
||||||
void (*func) (qse_stx_t*,qse_word_t,void*), void* data)
|
void (*func) (qse_stx_t*,qse_word_t,void*), void* data)
|
||||||
|
@ -21,39 +21,44 @@ qse_word_t qse_stx_newsymbol (
|
|||||||
{
|
{
|
||||||
qse_stx_symtab_t* tabptr;
|
qse_stx_symtab_t* tabptr;
|
||||||
qse_word_t symref;
|
qse_word_t symref;
|
||||||
qse_stx_charobjptr_t symptr;
|
qse_word_t capa, hash, tally;
|
||||||
qse_word_t capa, hash, count;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* the table must have at least one slot excluding the tally field */
|
/* the table must have at least one slot excluding the tally field */
|
||||||
QSE_ASSERT (OBJSIZE(stx,tabref) > 1);
|
QSE_ASSERT (OBJSIZE(stx,tabref) > 1);
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
capa = OBJSIZE(stx,tabref) - 1; /* exclude the tally field */
|
capa = OBJSIZE(stx,tabref) - 1; /* exclude the tally field */
|
||||||
hash = qse_stx_hashstr (stx, name) % capa;
|
hash = qse_stx_hashstr (stx, name) % capa;
|
||||||
|
|
||||||
tabptr = (qse_stx_symtab_t*)PTRBYREF(stx,tabref);
|
tabptr = (qse_stx_symtab_t*)PTRBYREF(stx,tabref);
|
||||||
for (count = 0; count < capa; count++)
|
tally = REFTOINT(stx, tabptr->tally);
|
||||||
|
|
||||||
|
do
|
||||||
{
|
{
|
||||||
symref = tabptr->slot[hash];
|
symref = tabptr->slot[hash];
|
||||||
if (symref == stx->ref.nil) break; /* not found */
|
if (symref == stx->ref.nil) break; /* not found */
|
||||||
|
|
||||||
|
QSE_ASSERT (REFISIDX(stx,symref));
|
||||||
|
QSE_ASSERT (OBJCLASS(stx,symref) == stx->ref.class_symbol);
|
||||||
QSE_ASSERT (OBJTYPE(stx,symref) == CHAROBJ);
|
QSE_ASSERT (OBJTYPE(stx,symref) == CHAROBJ);
|
||||||
symptr = (qse_stx_charobjptr_t) PTRBYREF (stx, symref);
|
|
||||||
|
|
||||||
if (qse_strcmp (name, symptr->fld) == 0) return symref;
|
/*if (qse_strxcmp (
|
||||||
|
&CHARAT(stx,symref,0), OBJSIZE(stx,symref),
|
||||||
|
name) == 0) return symref;*/
|
||||||
|
if (qse_strcmp (&CHARAT(stx,symref,0), name) == 0) return symref;
|
||||||
|
|
||||||
hash = (hash + 1) % capa;
|
hash = (hash + 1) % capa;
|
||||||
}
|
}
|
||||||
|
while (0);
|
||||||
|
|
||||||
if (tabptr->tally >= capa)
|
if (tally + 1 >= capa)
|
||||||
{
|
{
|
||||||
|
/* Enlarge the symbol table before it gets full to make sure that
|
||||||
|
* it has at least one free slot. */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* TODO: write this part....
|
|
||||||
if (grow (stx, tab) <= -1) return -1;
|
if (grow (stx, tab) <= -1) return -1;
|
||||||
/* refresh tally */
|
/* refresh tally */
|
||||||
tally = QSE_STX_REFTOINT(QSE_STX_WORDAT(stx,tab,QSE_STX_SET_TALLY));
|
tally = REFTOINT (stx, tabptr->tally);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,8 +66,10 @@ qse_word_t qse_stx_newsymbol (
|
|||||||
if (symref != stx->ref.nil)
|
if (symref != stx->ref.nil)
|
||||||
{
|
{
|
||||||
OBJCLASS(stx,symref) = stx->ref.class_symbol;
|
OBJCLASS(stx,symref) = stx->ref.class_symbol;
|
||||||
|
tabptr->tally = INTTOREF (stx, tally + 1);
|
||||||
tabptr->slot[hash] = symref;
|
tabptr->slot[hash] = symref;
|
||||||
}
|
}
|
||||||
|
|
||||||
return symref;
|
return symref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user