diff --git a/qse/lib/stx/boot.c b/qse/lib/stx/boot.c index 67fc10e2..532fda60 100644 --- a/qse/lib/stx/boot.c +++ b/qse/lib/stx/boot.c @@ -6,8 +6,8 @@ #include static int make_intrinsic_classes (qse_stx_t* stx); -#if 0 -static qse_word_t __make_classvar_dict ( + +static qse_word_t __make_classvar_dic ( qse_stx_t* stx, qse_word_t class, const qse_char_t* names); static void __filein_kernel (qse_stx_t* stx); @@ -20,7 +20,6 @@ static void __set_subclasses ( qse_stx_t* stx, qse_word_t* array, const qse_char_t* str); static void __set_metaclass_subclasses ( qse_stx_t* stx, qse_word_t* array, const qse_char_t* str); -#endif struct class_info_t { @@ -284,7 +283,7 @@ qse_word_t QSE_INLINE new_string (qse_stx_t* stx, const qse_char_t* str) qse_word_t x; QSE_ASSERT (REFISIDX(stx,stx->ref.class_string)); - QSE_ASSERT (stx->ref.class_string != stx->ref.nil); + QSE_ASSERT (!ISNIL(stx,stx->ref.class_string)); x = qse_stx_alloccharobj (stx, str, qse_strlen(str)); if (x != stx->ref.nil) OBJCLASS(stx,x) = stx->ref.class_string; @@ -295,89 +294,98 @@ qse_word_t QSE_INLINE new_string (qse_stx_t* stx, const qse_char_t* str) static int make_intrinsic_classes (qse_stx_t* stx) { class_info_t* p; - qse_word_t class, superclass, array; - qse_stx_class_t* class_obj, * superclass_obj; - qse_word_t metaclass; - qse_stx_metaclass_t* metaclass_obj; - qse_word_t n, nfields; + qse_word_t n; - QSE_ASSERT (stx->class_array != stx->ref.nil); + QSE_ASSERT (!ISNIL(stx,stx->ref.class_array)); for (p = class_info; p->name != QSE_NULL; p++) { - class = qse_stx_findclass(stx, p->name); - if (class == stx->ref.nil) + qse_word_t classref; + qse_stx_class_t* classptr; + qse_word_t nfixed; + + classref = qse_stx_findclass(stx, p->name); + if (ISNIL(stx,classref)) { - class = qse_stx_newclass (stx, p->name); - if (class == stx->ref.nil) return stx->ref.nil; + classref = qse_stx_newclass (stx, p->name); + if (ISNIL(stx,classref)) return NIL(stx); } - QSE_ASSERT (class != stx->ref.nil); - - class_obj = (qse_stx_class_t*)PTRBYREF(stx,class); + classptr = (qse_stx_class_t*)PTRBYREF(stx,classref); if (p->superclass) { - class_obj->superclass = qse_stx_findclass(stx,p->superclass); - QSE_ASSERT (class_obj->superclass != stx->ref.nil); + classptr->superclass = qse_stx_findclass(stx,p->superclass); + QSE_ASSERT (!ISNIL(stx,classptr->superclass)); } - nfields = 0; + nfixed = 0; + + /* resolve the number of fixed fields in the superclass chain */ if (p->superclass) { - qse_word_t meta; - qse_stx_metaclass_t* meta_obj; + qse_word_t superref; + qse_stx_class_t* superptr; - superclass = qse_stx_findclass (stx, p->superclass); - QSE_ASSERT (superclass != stx->ref.nil); + qse_word_t metaref; + qse_stx_metaclass_t* metaptr; - meta = class_obj->h._class; - meta_obj = (qse_stx_metaclass_t*)PTRBYREF(stx,meta); - meta_obj->superclass = OBJCLASS(stx,superclass); - meta_obj->instance_class = class; + superref = qse_stx_findclass (stx, p->superclass); + QSE_ASSERT (!ISNIL(stx,superref)); - while (superclass != stx->ref.nil) + metaref = OBJCLASS(stx,classref); + metaptr = (qse_stx_metaclass_t*)PTRBYREF(stx,metaref); + metaptr->superclass = OBJCLASS(stx,superref); + metaptr->instance_class = classref; + + do { - superclass_obj = (qse_stx_class_t*) - QSE_STX_OBJPTR(stx,superclass); - nfields += - QSE_STX_FROMSMALLINT(superclass_obj->spec) >> - QSE_STX_SPEC_INDEXABLE_BITS; - superclass = superclass_obj->superclass; + superptr = (qse_stx_class_t*)PTRBYREF(stx,superref); + nfixed += SPEC_GETFIXED(REFTOINT(stx,superptr->spec)); + superref = superptr->superclass; } + while (!ISNIL(stx,superref)); } + /* add the number of instance variables to the number of + * fixed fields */ if (p->instance_variables) { - nfields += __count_names (p->instance_variables); - class_obj->variables = + nfixed += __count_names (p->instance_variables); + classptr->variables = new_string (stx, p->instance_variables); - if (class_obj->variables == stx->ref.nil) return -1; + if (ISNIL(stx,classptr->variables)) return -1; } - QSE_ASSERT (nfields <= 0 || (nfields > 0 && - (p->spec == SPEC_FIXED_WORD || - p->spec == SPEC_VARIABLE_WORD))); + QSE_ASSERT ( + nfixed <= 0 || + (nfixed > 0 && (p->spec == SPEC_FIXED_WORD || + p->spec == SPEC_VARIABLE_WORD))); - class_obj->spec = MAKE_SPEC (nfields, p->spec); + classptr->spec = SPEC_MAKE (nfixed, p->spec); } for (p = class_info; p->name != QSE_NULL; p++) { - class = qse_stx_lookup_class(stx, p->name); - QSE_ASSERT (class != stx->ref.nil); + qse_word_t classref; + qse_stx_class_t* classptr; - class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class); + classref = qse_stx_findclass (stx, p->name); + QSE_ASSERT (!ISNIL(stx,classref)); + + classptr = (qse_stx_class_t*)PTRBYREF(stx,classref); if (p->class_variables != QSE_NULL) { - class_obj->class_variables = - __make_classvar_dict(stx, class, p->class_variables); + classptr->class_variables = + __make_classvar_dic(stx, classref, p->class_variables); + + if (ISNIL(stx,classptr->class_variables)) return NIL(stx); } /* TODO: if (p->pool_dictionaries != QSE_NULL) { - class_obj->pool_dictionaries = + classptr->pool_dictionaries = __make_pool_dictionary(stx, class, p->pool_dictionaries); } */ @@ -386,28 +394,44 @@ static int make_intrinsic_classes (qse_stx_t* stx) /* fill subclasses */ for (p = class_info; p->name != QSE_NULL; p++) { - n = __count_subclasses (p->name); - array = qse_stx_new_array (stx, n); - __set_subclasses (stx, QSE_STX_DATA(stx,array), p->name); + qse_word_t classref; + qse_stx_class_t* classptr; + qse_word_t array; - class = qse_stx_lookup_class(stx, p->name); - QSE_ASSERT (class != stx->ref.nil); - class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class); - class_obj->subclasses = array; + n = __count_subclasses (p->name); + array = qse_stx_newarray (stx, n); + if (ISNIL(stx,array)) return NIL(stx); + + __set_subclasses (stx, &WORDAT(stx,array,0), p->name); + + classref = qse_stx_findclass (stx, p->name); + QSE_ASSERT (!ISNIL(stx,classref)); + + classptr = (qse_stx_class_t*)PTRBYREF(stx,classref); + classptr->subclasses = array; } /* fill subclasses for metaclasses */ for (p = class_info; p->name != QSE_NULL; p++) { + qse_word_t classref; + qse_stx_class_t* classptr; + + qse_word_t metaref; + qse_stx_metaclass_t* metaptr; + + qse_word_t array; + n = __count_subclasses (p->name); array = qse_stx_new_array (stx, n); - __set_metaclass_subclasses (stx, QSE_STX_DATA(stx,array), p->name); + __set_metaclass_subclasses (stx, &WORDAT(stx,array,0), p->name); - class = qse_stx_lookup_class(stx, p->name); - QSE_ASSERT (class != stx->ref.nil); - metaclass = QSE_STX_CLASS(stx,class); - metaclass_obj = (qse_stx_metaclass_t*)QSE_STX_OBJPTR(stx, metaclass); - metaclass_obj->subclasses = array; + classref = qse_stx_findclass (stx, p->name); + QSE_ASSERT (!ISNIL(stx,classref)); + + metaref = OBJCLASS(stx,classref); + metaptr = (qse_stx_metaclass_t*)PTRBYREF(stx,metaref); + metaptr->subclasses = array; } return 0; @@ -418,7 +442,8 @@ static qse_word_t __count_names (const qse_char_t* str) qse_word_t n = 0; const qse_char_t* p = str; - do { + do + { while (*p == QSE_T(' ') || *p == QSE_T('\t')) p++; if (*p == QSE_T('\0')) break; @@ -427,7 +452,8 @@ static qse_word_t __count_names (const qse_char_t* str) while (*p != QSE_T(' ') && *p != QSE_T('\t') && *p != QSE_T('\0')) p++; - } while (1); + } + while (1); return n; } @@ -439,7 +465,8 @@ static void __set_names ( const qse_char_t* p = str; const qse_char_t* name; - do { + do + { while (*p == QSE_T(' ') || *p == QSE_T('\t')) p++; if (*p == QSE_T('\0')) break; @@ -449,8 +476,9 @@ static void __set_names ( *p != QSE_T('\t') && *p != QSE_T('\0')) p++; - array[n++] = qse_stx_new_symbolx (stx, name, p - name); - } while (1); + array[n++] = qse_stx_newsymbolx (stx, name, p - name); + } + while (1); } static qse_word_t __count_subclasses (const qse_char_t* str) @@ -458,7 +486,8 @@ static qse_word_t __count_subclasses (const qse_char_t* str) class_info_t* p; qse_word_t n = 0; - for (p = class_info; p->name != QSE_NULL; p++) { + for (p = class_info; p->name != QSE_NULL; p++) + { if (p->superclass == QSE_NULL) continue; if (qse_strcmp (str, p->superclass) == 0) n++; } @@ -472,11 +501,12 @@ static void __set_subclasses ( class_info_t* p; qse_word_t n = 0, class; - for (p = class_info; p->name != QSE_NULL; p++) { + for (p = class_info; p->name != QSE_NULL; p++) + { if (p->superclass == QSE_NULL) continue; if (qse_strcmp (str, p->superclass) != 0) continue; - class = qse_stx_lookup_class (stx, p->name); - QSE_ASSERT (class != stx->ref.nil); + class = qse_stx_findclass (stx, p->name); + QSE_ASSERT (!ISNIL(stx,class)); array[n++] = class; } } @@ -487,27 +517,31 @@ static void __set_metaclass_subclasses ( class_info_t* p; qse_word_t n = 0, class; - for (p = class_info; p->name != QSE_NULL; p++) { + for (p = class_info; p->name != QSE_NULL; p++) + { if (p->superclass == QSE_NULL) continue; if (qse_strcmp (str, p->superclass) != 0) continue; - class = qse_stx_lookup_class (stx, p->name); - QSE_ASSERT (class != stx->ref.nil); - array[n++] = QSE_STX_CLASS(stx,class); + class = qse_stx_findclass (stx, p->name); + QSE_ASSERT (!ISNIL(stx,class)); + array[n++] = OBJCLASS(stx,class); } } -static qse_word_t __make_classvar_dict ( +static qse_word_t __make_classvar_dic ( qse_stx_t* stx, qse_word_t class, const qse_char_t* names) { - qse_word_t dict, symbol; + qse_word_t dic, symbol, assoc; const qse_char_t* p = names; const qse_char_t* name; - dict = qse_stx_instantiate ( - stx, stx->class_systemdictionary, +/* TODO: how to implement temporary GC prevention....???? */ + dic = qse_stx_instantiate ( + stx, stx->ref.class_systemdictionary, QSE_NULL, QSE_NULL, __count_names(names)); + if (ISNIL(stx,dic)) return NIL(stx); - do { + do + { while (*p == QSE_T(' ') || *p == QSE_T('\t')) p++; if (*p == QSE_T('\0')) break; @@ -517,11 +551,15 @@ static qse_word_t __make_classvar_dict ( *p != QSE_T('\t') && *p != QSE_T('\0')) p++; - symbol = qse_stx_new_symbolx (stx, name, p - name); - qse_stx_dict_put (stx, dict, symbol, stx->ref.nil); - } while (1); + symbol = qse_stx_newsymbolx (stx, name, p - name); + if (ISNIL(stx,symbol)) return NIL(stx); - return dict; + assoc =qse_stx_putdic (stx, dic, symbol, stx->ref.nil); + if (ISNIL(stx,assoc)) return NIL(stx); + } + while (1); + + return dic; } static void __filein_kernel (qse_stx_t* stx) @@ -532,7 +570,6 @@ static void __filein_kernel (qse_stx_t* stx) /* TODO: */ } } -#endif static int sketch_nil (qse_stx_t* stx) { @@ -608,22 +645,22 @@ static int sketch_key_objects (qse_stx_t* stx) WORDAT(stx,stx->ref.sysdic,QSE_STX_DIC_TALLY) = INTTOREF(stx,0); /* Symbol */ - ALLOC_WORDOBJ_TO (stx, stx->ref.class_symbol, QSE_STX_CLASS_NFLDS, 0); + ALLOC_WORDOBJ_TO (stx, stx->ref.class_symbol, QSE_STX_CLASS_SIZE, 0); /* Metaclass */ - ALLOC_WORDOBJ_TO (stx, stx->ref.class_metaclass, QSE_STX_CLASS_NFLDS, 0); + ALLOC_WORDOBJ_TO (stx, stx->ref.class_metaclass, QSE_STX_CLASS_SIZE, 0); /* Association */ - ALLOC_WORDOBJ_TO (stx, stx->ref.class_association, QSE_STX_CLASS_NFLDS, 0); + ALLOC_WORDOBJ_TO (stx, stx->ref.class_association, QSE_STX_CLASS_SIZE, 0); /* Metaclass is a class so it has the same structure * as a normal class. "Metaclass class" is an instance of * Metaclass. */ /* Symbol class */ - ALLOC_WORDOBJ_TO (stx, class_SymbolMeta, QSE_STX_METACLASS_NFLDS, 0); + ALLOC_WORDOBJ_TO (stx, class_SymbolMeta, QSE_STX_METACLASS_SIZE, 0); /* Metaclass class */ - ALLOC_WORDOBJ_TO (stx, class_MetaclassMeta, QSE_STX_METACLASS_NFLDS, 0); + ALLOC_WORDOBJ_TO (stx, class_MetaclassMeta, QSE_STX_METACLASS_SIZE, 0); /* Association class */ - ALLOC_WORDOBJ_TO (stx, class_AssociationMeta, QSE_STX_METACLASS_NFLDS, 0); + ALLOC_WORDOBJ_TO (stx, class_AssociationMeta, QSE_STX_METACLASS_SIZE, 0); /* (Symbol class) setClass: Metaclass */ QSE_STX_OBJCLASS(stx,class_SymbolMeta) = stx->ref.class_metaclass; @@ -641,13 +678,13 @@ static int sketch_key_objects (qse_stx_t* stx) /* (Symbol class) setSpec: CLASS_SIZE */ WORDAT(stx,class_SymbolMeta,QSE_STX_CLASS_SPEC) = - INTTOREF (stx, MAKE_SPEC(QSE_STX_CLASS_NFLDS,SPEC_FIXED_WORD)); + INTTOREF (stx, SPEC_MAKE(QSE_STX_CLASS_SIZE,SPEC_FIXED_WORD)); /* (Metaclass class) setSpec: CLASS_SIZE */ WORDAT(stx,class_MetaclassMeta,QSE_STX_CLASS_SPEC) = - INTTOREF (stx, MAKE_SPEC(QSE_STX_CLASS_NFLDS,SPEC_FIXED_WORD)); + INTTOREF (stx, SPEC_MAKE(QSE_STX_CLASS_SIZE,SPEC_FIXED_WORD)); /* (Association class) setSpec: CLASS_SIZE */ WORDAT(stx,class_AssociationMeta,QSE_STX_CLASS_SPEC) = - INTTOREF (stx, MAKE_SPEC(QSE_STX_CLASS_NFLDS,SPEC_FIXED_WORD)); + INTTOREF (stx, SPEC_MAKE(QSE_STX_CLASS_SIZE,SPEC_FIXED_WORD)); /* specs for class_metaclass, class_association, * class_symbol are set later in make_builtin_classes */ diff --git a/qse/lib/stx/cls.c b/qse/lib/stx/cls.c index 4353e3d6..1603e406 100644 --- a/qse/lib/stx/cls.c +++ b/qse/lib/stx/cls.c @@ -4,32 +4,6 @@ #include "stx.h" -struct qse_stx_class_t -{ - qse_stx_objhdr_t h; - qse_word_t spec; /* indexable: 2, nfields: the rest */ - qse_word_t methods; - qse_word_t superclass; - qse_word_t subclasses; - qse_word_t name; - qse_word_t variables; - qse_word_t class_variables; - qse_word_t pool_dictonaries; -}; - -struct qse_stx_metaclass_t -{ - qse_stx_objhdr_t h; - qse_word_t spec; - qse_word_t methods; - qse_word_t superclass; - qse_word_t subclasses; - qse_word_t instance_class; -}; - -typedef struct qse_stx_class_t qse_stx_class_t; -typedef struct qse_stx_metaclass_t qse_stx_metaclass_t; - qse_word_t qse_stx_newclass (qse_stx_t* stx, const qse_char_t* name) { qse_word_t meta, class; @@ -45,7 +19,7 @@ qse_word_t qse_stx_newclass (qse_stx_t* stx, const qse_char_t* name) /* the spec of the metaclass must be the spec of its * instance. so the QSE_STX_CLASS_SIZE is set */ WORDAT(stx,meta,QSE_STX_METACLASS_SPEC) = - INTTOREF(stx,MAKE_SPEC(QSE_STX_CLASS_SIZE,SPEC_FIXED_WORD)); + INTTOREF(stx,SPEC_MAKE(QSE_STX_CLASS_SIZE,SPEC_FIXED_WORD)); /* the spec of the class is set later in __create_builtin_classes */ class = qse_stx_allocwordobj ( diff --git a/qse/lib/stx/cls.h b/qse/lib/stx/cls.h index dd0f588e..c24b1ace 100644 --- a/qse/lib/stx/cls.h +++ b/qse/lib/stx/cls.h @@ -5,6 +5,32 @@ #ifndef _QSE_LIB_STX_CLS_H_ #define _QSE_LIB_STX_CLS_H_ +struct qse_stx_class_t +{ + qse_stx_objhdr_t h; + qse_word_t spec; /* indexable: 2, nfields: the rest */ + qse_word_t methods; + qse_word_t superclass; + qse_word_t subclasses; + qse_word_t name; + qse_word_t variables; + qse_word_t class_variables; + qse_word_t pool_dictonaries; +}; + +struct qse_stx_metaclass_t +{ + qse_stx_objhdr_t h; + qse_word_t spec; + qse_word_t methods; + qse_word_t superclass; + qse_word_t subclasses; + qse_word_t instance_class; +}; + +typedef struct qse_stx_class_t qse_stx_class_t; +typedef struct qse_stx_metaclass_t qse_stx_metaclass_t; + #define QSE_STX_CLASS_SIZE 8 #define QSE_STX_CLASS_SPEC 0 #define QSE_STX_CLASS_METHODS 1 @@ -30,8 +56,10 @@ #define SPEC_VARIABLE_BYTE 0x02 #define SPEC_VARIABLE_CHAR 0x03 -#define MAKE_SPEC(nflds,variable) \ - (((nflds) << SPEC_VARIABLE_BITS) | (variable)) +#define SPEC_MAKE(fixed,variable) \ + (((fixed) << SPEC_VARIABLE_BITS) | (variable)) + +#define SPEC_GETFIXED(spec) ((spec) >> SPEC_VARIABLE_BITS) #ifdef __cplusplus extern "C" { diff --git a/qse/lib/stx/dic.c b/qse/lib/stx/dic.c index 4ecb00f8..d8761420 100644 --- a/qse/lib/stx/dic.c +++ b/qse/lib/stx/dic.c @@ -40,52 +40,78 @@ static qse_word_t new_assoc ( OBJCLASS(stx,x) = stx->ref.class_association; WORDAT(stx,x,QSE_STX_ASSOC_KEY) = key; WORDAT(stx,x,QSE_STX_ASSOC_VALUE) = value; - return x; } static qse_word_t expand (qse_stx_t* stx, qse_word_t dic) { - qse_word_t newref, size, index, assoc; + qse_word_t oldcapa, newdic, newcapa; + qse_stx_dic_t* oldptr, * newptr; + QSE_ASSERT (REFISIDX(stx,stx->ref.class_systemdictionary)); + QSE_ASSERT (stx->ref.class_systemdictionary != stx->ref.nil); + + QSE_ASSERTX ( + REFISIDX(stx,dic), + "The reference is not an object index" + ); + /* WARNING: * if this assertion fails, adjust the initial size of the * system dicionary. i don't want this function to be called * during the bootstrapping. */ - QSE_ASSERT (stx->ref.class_systemdictionary != stx->ref.nil); - QSE_ASSERT (REFISIDX(stx,dic)); QSE_ASSERT (OBJCLASS(stx,dic) == stx->ref.class_systemdictionary); - size = OBJSIZE(stx,dic); - newref = qse_stx_instantiate (stx, - OBJCLASS(stx,dic), QSE_NULL, QSE_NULL, (size - 1) * 2); - if (newref == stx->ref.nil) return stx->ref.nil; - WORDAT(stx,newref,QSE_STX_DIC_TALLY) = INTTOREF (stx, 0); + /* get the current capacity excluding the tally field */ + oldcapa = OBJSIZE(stx,dic) - 1; + + /* instantiate a new dictionary with its capacity doubled. + * 1 fixed slot for the tally field is encoded is the class part. + * so 'newcapa' specifies the number of slots to hold associations */ + newcapa = oldcapa * 2; + newdic = qse_stx_instantiate ( + stx, OBJCLASS(stx,dic), + QSE_NULL, QSE_NULL, newcapa + ); + if (newdic == stx->ref.nil) return stx->ref.nil; - for (index = 1; index < size; index++) + /* get object pointers for easier access without using macros */ + oldptr = (qse_stx_dic_t*)PTRBYREF(stx,dic); + newptr = (qse_stx_dic_t*)PTRBYREF(stx,newdic); + newptr->tally = INTTOREF(stx,0); + + QSE_ASSERT (newcapa == OBJSIZE(stx,newdic)-1); + + /* reorganize the dictionary */ + while (oldcapa > 0) { - assoc = WORDAT(stx,dic,index); - if (assoc == stx->ref.nil) continue; + qse_word_t assoc; - if (qse_stx_putdic (stx, newref, - WORDAT(stx,assoc,QSE_STX_ASSOC_KEY), - WORDAT(stx,assoc,QSE_STX_ASSOC_VALUE)) == stx->ref.nil) + assoc = oldptr->slot[--oldcapa]; + if (assoc != stx->ref.nil) { - return stx->ref.nil; + qse_word_t index; + + index = qse_stx_hashobj (stx, WORDAT(stx,assoc,QSE_STX_ASSOC_KEY)) % newcapa; + while (newptr->slot[index] != stx->ref.nil) + index = (index + 1) % newcapa; + newptr->slot[index] = assoc; } } + newptr->tally = oldptr->tally; + /* TODO: explore if dic can be immediately destroyed. */ - qse_stx_swapmem (stx, REFTOIDX(stx,dic), REFTOIDX(stx,newref)); + qse_stx_swapmem (stx, REFTOIDX(stx,dic), REFTOIDX(stx,newdic)); return dic; } -static qse_word_t find_slot ( +static qse_word_t find_basic_index ( qse_stx_t* stx, qse_word_t dic, qse_word_t key) { - qse_word_t capa, hash; + qse_word_t capa, index; qse_stx_dic_t* dicptr; /* ensure that dic is a system dictionary */ @@ -100,7 +126,7 @@ static qse_word_t find_slot ( QSE_ASSERT (OBJTYPE(stx,key) == CHAROBJ); capa = OBJSIZE(stx,dic) - 1; /* exclude the tally field */ - hash = qse_stx_hashobj (stx, key) % capa; + index = qse_stx_hashobj (stx, key) % capa; dicptr = (qse_stx_dic_t*)PTRBYREF(stx,dic); @@ -108,33 +134,35 @@ static qse_word_t find_slot ( { qse_word_t assoc, sym; - assoc = dicptr->slot[hash]; + assoc = dicptr->slot[index]; if (assoc == stx->ref.nil) break; /* not found */ sym = WORDAT (stx, assoc, QSE_STX_ASSOC_KEY); + /* make sure that the key is a symbol */ QSE_ASSERT (REFISIDX(stx,sym)); QSE_ASSERT (OBJCLASS(stx,sym) == stx->ref.class_symbol); QSE_ASSERT (OBJTYPE(stx,sym) == CHAROBJ); + /* check if the key matches */ if (qse_strxncmp( &CHARAT(stx,key,0), OBJSIZE(stx,key), &CHARAT(stx,sym,0), OBJSIZE(stx,sym)) == 0) break; - hash = (hash + 1) % capa; + index = (index + 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; + return index + 1; } /* look up a system dictionary by a null-terminated string */ qse_word_t qse_stx_lookupdic ( qse_stx_t* stx, qse_word_t dic, const qse_char_t* skey) { - qse_word_t capa, hash; + qse_word_t capa, index; qse_stx_dic_t* dicptr; QSE_ASSERT (REFISIDX(stx,dic)); @@ -143,7 +171,7 @@ qse_word_t qse_stx_lookupdic ( OBJCLASS(stx,dic) == stx->ref.class_systemdictionary); capa = OBJSIZE(stx,dic) - 1; /* exclude the tally field */ - hash = qse_stx_hashstr (stx, skey) % capa; + index = qse_stx_hashstr (stx, skey) % capa; dicptr = (qse_stx_dic_t*)PTRBYREF(stx,dic); @@ -151,7 +179,7 @@ qse_word_t qse_stx_lookupdic ( { qse_word_t assoc, keyref; - assoc = dicptr->slot[hash]; + assoc = dicptr->slot[index]; if (assoc == stx->ref.nil) break; /* not found */ keyref = WORDAT(stx,assoc,QSE_STX_ASSOC_KEY); @@ -164,22 +192,23 @@ qse_word_t qse_stx_lookupdic ( &CHARAT(stx,keyref,0), OBJSIZE(stx,keyref), skey) == 0) break; - hash = (hash + 1) % capa; + index = (index + 1) % capa; } while (1); - return dicptr->slot[hash]; + return dicptr->slot[index]; } 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)); + /* returns the association for the key. nil if it is not found */ + return WORDAT (stx, dic, find_basic_index (stx, dic, key)); } qse_word_t qse_stx_putdic ( 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 index, capa, tally, assoc; qse_stx_dic_t* dicptr; /* the dicionary must have at least one slot excluding tally */ @@ -188,10 +217,11 @@ qse_word_t qse_stx_putdic ( capa = OBJSIZE(stx,dic) - 1; dicptr = (qse_stx_dic_t*)PTRBYREF(stx,dic); - tally = REFTOINT(stx,WORDAT(stx,dic,QSE_STX_DIC_TALLY)); + tally = REFTOINT(stx,dicptr->tally); + index = find_basic_index (stx, dic, key) - 1; + assoc = dicptr->slot[index]; - slot = find_slot (stx, dic, key); - assoc = WORDAT(stx,dic,slot); + /*assoc = WORDAT(stx,dic,slot);*/ if (assoc == stx->ref.nil) { @@ -207,15 +237,23 @@ qse_word_t qse_stx_putdic ( */ if (expand (stx, dic) == stx->ref.nil) return stx->ref.nil; - /* refresh tally */ - tally = REFTOINT(stx,WORDAT(stx,dic,QSE_STX_DIC_TALLY)); + capa = OBJSIZE(stx,dic) - 1; + dicptr = (qse_stx_dic_t*)PTRBYREF(stx,dic); + /* tally must remain the same after expansion */ + QSE_ASSERT (tally == REFTOINT(stx,dicptr->tally)); + + /* find the key in the expanded dictionary again */ + index = find_basic_index (stx, dic, key) - 1; + /* the basic index returned must point to nil meaning + * the key is not found */ + QSE_ASSERT (dicptr->slot[index] == stx->ref.nil); } assoc = new_assoc (stx, key, value); if (assoc == stx->ref.nil) return stx->ref.nil; - WORDAT(stx,dic,slot) = assoc; - WORDAT(stx,dic,QSE_STX_DIC_TALLY) = INTTOREF(stx,tally + 1); + dicptr->slot[index] = assoc; + dicptr->tally = INTTOREF(stx,tally+1); } else { diff --git a/qse/lib/stx/stx.h b/qse/lib/stx/stx.h index 67e117bc..5ed27657 100644 --- a/qse/lib/stx/stx.h +++ b/qse/lib/stx/stx.h @@ -18,14 +18,6 @@ typedef struct qse_stx_byteobj_t qse_stx_byteobj_t; typedef struct qse_stx_charobj_t qse_stx_charobj_t; typedef struct qse_stx_wordobj_t qse_stx_wordobj_t; -#include "hash.h" -#include "mem.h" -#include "obj.h" -#include "sym.h" -#include "dic.h" -#include "cls.h" -#include "boot.h" - enum qse_stx_objtype_t { QSE_STX_BYTEOBJ = 0, @@ -63,6 +55,14 @@ word fixed qse_word_t _backref; }; +#include "hash.h" +#include "mem.h" +#include "obj.h" +#include "sym.h" +#include "dic.h" +#include "cls.h" +#include "boot.h" + struct qse_stx_object_t { qse_stx_objhdr_t h; @@ -209,6 +209,9 @@ struct qse_stx_t #define SYMTAB_INIT_CAPA 256 #define SYSDIC_INIT_CAPA 256 +#define ISNIL(stx,obj) ((obj) == (stx)->ref.nil) +#define NIL(stx) ((stx)->ref.nil) + #ifdef __cplusplus extern "C" { #endif diff --git a/qse/lib/stx/sym.c b/qse/lib/stx/sym.c index cb0cd775..3e5547d0 100644 --- a/qse/lib/stx/sym.c +++ b/qse/lib/stx/sym.c @@ -22,6 +22,9 @@ static qse_word_t expand (qse_stx_t* stx, qse_word_t tabref) qse_word_t newtab; qse_stx_symtab_t* oldptr, * newptr; + QSE_ASSERT (REFISIDX(stx,stx->ref.class_systemsymboltable)); + QSE_ASSERT (!ISNIL(stx,stx->ref.class_systemsymboltable)); + QSE_ASSERTX ( REFISIDX(stx,tabref), "The reference is not an object index" @@ -43,21 +46,24 @@ static qse_word_t expand (qse_stx_t* stx, qse_word_t tabref) /* instantiate a new symbol table with its capacity doubled. */ newcapa = oldcapa * 2; newtab = qse_stx_instantiate ( - stx, OBJCLASS(stx,tabref), - QSE_NULL, QSE_NULL, newcapa + 1 + stx, OBJCLASS(stx,tabref), + QSE_NULL, QSE_NULL, newcapa ); - if (newtab == stx->ref.nil) return stx->ref.nil; + if (ISNIL(stx,newtab)) return NIL(stx); oldptr = (qse_stx_symtab_t*)PTRBYREF(stx,tabref); newptr = (qse_stx_symtab_t*)PTRBYREF(stx,newtab); newptr->tally = INTTOREF (stx, 0); + QSE_ASSERT (newcapa == OBJSIZE(stx,newtab) - 1); + + /* reorganize the symbol table */ while (oldcapa > 0) { qse_word_t symbol; symbol = oldptr->slot[--oldcapa]; - if (symbol != stx->ref.nil) + if (!ISNIL(stx,symbol)) { qse_word_t index; @@ -72,15 +78,14 @@ static qse_word_t expand (qse_stx_t* stx, qse_word_t tabref) qse_stx_hashstr (stx, &CHARAT(stx,symbol,0))); index = qse_stx_hashobj (stx, symbol) % newcapa; - while (newptr->slot[index] != stx->ref.nil) + while (!ISNIL(stx,newptr->slot[index])) index = (index + 1) % newcapa; newptr->slot[index] = symbol; } } - qse_stx_swapmem (stx, REFTOIDX(stx,tabref), REFTOIDX(stx,newtab)); - newptr->tally = oldptr->tally; + qse_stx_swapmem (stx, REFTOIDX(stx,tabref), REFTOIDX(stx,newtab)); return tabref; } @@ -105,7 +110,7 @@ static qse_word_t new_symbol ( { /*symref = WORDAT (stx, tabref, index + 1);*/ symref = tabptr->slot[index]; - if (symref == stx->ref.nil) break; /* not found */ + if (ISNIL(stx,symref)) break; /* not found */ QSE_ASSERT (REFISIDX(stx,symref)); QSE_ASSERT (OBJCLASS(stx,symref) == stx->ref.class_symbol); @@ -130,7 +135,7 @@ static qse_word_t new_symbol ( * make sure that it has at least one free slot left * after having added a new symbol. this is to help * traversal end at a nil slot if no entry is found. */ - if (expand (stx, tabref) == stx->ref.nil) return stx->ref.nil; + if (ISNIL (stx, expand (stx, tabref))) return NIL(stx); /* refresh the object pointer */ tabptr = (qse_stx_symtab_t*)PTRBYREF(stx,tabref); @@ -144,7 +149,7 @@ static qse_word_t new_symbol ( } symref = qse_stx_alloccharobj (stx, name, qse_strlen(name)); - if (symref != stx->ref.nil) + if (!ISNIL(stx,symref)) { OBJCLASS(stx,symref) = stx->ref.class_symbol; tabptr->tally = INTTOREF (stx, tally + 1);