added more code for symbol table, system dictionary, bootstrapping

This commit is contained in:
hyung-hwan 2011-06-15 10:04:31 +00:00
parent 3cc4595018
commit fb46d98bb2
18 changed files with 784 additions and 443 deletions

View File

@ -8,6 +8,6 @@ AM_CPPFLAGS = \
lib_LTLIBRARIES = libqsestx.la lib_LTLIBRARIES = libqsestx.la
libqsestx_la_SOURCES = stx.c err.c hash.c mem.c obj.c sym.c dic.c boot.c libqsestx_la_SOURCES = stx.c err.c hash.c mem.c obj.c sym.c dic.c cls.c boot.c
libqsestx_la_LDFLAGS = -L../cmn -L$(libdir) -version-info 1:0:0 -no-undefined libqsestx_la_LDFLAGS = -L../cmn -L$(libdir) -version-info 1:0:0 -no-undefined
libqsestx_la_LIBADD = -lqsecmn libqsestx_la_LIBADD = -lqsecmn

View File

@ -72,7 +72,7 @@ am__installdirs = "$(DESTDIR)$(libdir)"
LTLIBRARIES = $(lib_LTLIBRARIES) LTLIBRARIES = $(lib_LTLIBRARIES)
libqsestx_la_DEPENDENCIES = libqsestx_la_DEPENDENCIES =
am_libqsestx_la_OBJECTS = stx.lo err.lo hash.lo mem.lo obj.lo sym.lo \ am_libqsestx_la_OBJECTS = stx.lo err.lo hash.lo mem.lo obj.lo sym.lo \
dic.lo boot.lo dic.lo cls.lo boot.lo
libqsestx_la_OBJECTS = $(am_libqsestx_la_OBJECTS) libqsestx_la_OBJECTS = $(am_libqsestx_la_OBJECTS)
libqsestx_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ libqsestx_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@ -239,7 +239,7 @@ AM_CPPFLAGS = \
-I$(includedir) -I$(includedir)
lib_LTLIBRARIES = libqsestx.la lib_LTLIBRARIES = libqsestx.la
libqsestx_la_SOURCES = stx.c err.c hash.c mem.c obj.c sym.c dic.c boot.c libqsestx_la_SOURCES = stx.c err.c hash.c mem.c obj.c sym.c dic.c cls.c boot.c
libqsestx_la_LDFLAGS = -L../cmn -L$(libdir) -version-info 1:0:0 -no-undefined libqsestx_la_LDFLAGS = -L../cmn -L$(libdir) -version-info 1:0:0 -no-undefined
libqsestx_la_LIBADD = -lqsecmn libqsestx_la_LIBADD = -lqsecmn
all: all-am all: all-am
@ -317,6 +317,7 @@ distclean-compile:
-rm -f *.tab.c -rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boot.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boot.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cls.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/err.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/err.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@

View File

@ -3,11 +3,9 @@
*/ */
#include "stx.h" #include "stx.h"
#include "mem.h" #include <qse/cmn/str.h>
#include "sym.h"
#include "class.h"
static void make_intrinsic_classes (qse_stx_t* stx); static int make_intrinsic_classes (qse_stx_t* stx);
#if 0 #if 0
static qse_word_t __make_classvar_dict ( static qse_word_t __make_classvar_dict (
qse_stx_t* stx, qse_word_t class, const qse_char_t* names); qse_stx_t* stx, qse_word_t class, const qse_char_t* names);
@ -22,6 +20,7 @@ static void __set_subclasses (
qse_stx_t* stx, qse_word_t* array, const qse_char_t* str); qse_stx_t* stx, qse_word_t* array, const qse_char_t* str);
static void __set_metaclass_subclasses ( static void __set_metaclass_subclasses (
qse_stx_t* stx, qse_word_t* array, const qse_char_t* str); qse_stx_t* stx, qse_word_t* array, const qse_char_t* str);
#endif
struct class_info_t struct class_info_t
{ {
@ -213,6 +212,14 @@ static class_info_t class_info[] =
QSE_NULL, QSE_NULL,
SPEC_VARIABLE_BYTE SPEC_VARIABLE_BYTE
}, },
{
QSE_T("SystemSymbolTable"),
QSE_T("IndexedCollection"),
QSE_T("tally"),
QSE_NULL,
QSE_NULL,
SPEC_VARIABLE_WORD
},
{ {
QSE_T("Dictionary"), QSE_T("Dictionary"),
QSE_T("IndexedCollection"), QSE_T("IndexedCollection"),
@ -221,6 +228,7 @@ static class_info_t class_info[] =
QSE_NULL, QSE_NULL,
SPEC_VARIABLE_WORD SPEC_VARIABLE_WORD
}, },
{ {
QSE_T("SystemDictionary"), QSE_T("SystemDictionary"),
QSE_T("Dictionary"), QSE_T("Dictionary"),
@ -271,18 +279,20 @@ static class_info_t class_info[] =
} }
}; };
qse_word_t QSE_INLINE __new_string (qse_stx_t* stx, const qse_char_t* str) qse_word_t QSE_INLINE new_string (qse_stx_t* stx, const qse_char_t* str)
{ {
qse_word_t x; qse_word_t x;
QSE_ASSERT (stx->class_string != stx->nil); QSE_ASSERT (REFISIDX(stx,stx->ref.class_string));
x = qse_stx_alloc_char_object (stx, str); QSE_ASSERT (stx->ref.class_string != stx->ref.nil);
QSE_STX_CLASS(stx,x) = stx->class_string;
x = qse_stx_alloccharobj (stx, str, qse_strlen(str));
if (x != stx->ref.nil) OBJCLASS(stx,x) = stx->ref.class_string;
return x; return x;
} }
static void make_intrinsic_classes (qse_stx_t* stx) static int make_intrinsic_classes (qse_stx_t* stx)
{ {
class_info_t* p; class_info_t* p;
qse_word_t class, superclass, array; qse_word_t class, superclass, array;
@ -291,35 +301,42 @@ static void make_intrinsic_classes (qse_stx_t* stx)
qse_stx_metaclass_t* metaclass_obj; qse_stx_metaclass_t* metaclass_obj;
qse_word_t n, nfields; qse_word_t n, nfields;
QSE_ASSERT (stx->class_array != stx->nil); QSE_ASSERT (stx->class_array != stx->ref.nil);
for (p = class_info; p->name != QSE_NULL; p++) for (p = class_info; p->name != QSE_NULL; p++)
{ {
class = qse_stx_lookup_class(stx, p->name); class = qse_stx_findclass(stx, p->name);
if (class == stx->nil) if (class == stx->ref.nil)
{ {
class = qse_stx_newclass (stx, p->name); class = qse_stx_newclass (stx, p->name);
if (class == stx->ref.nil) return stx->ref.nil;
} }
QSE_ASSERT (class != stx->nil); QSE_ASSERT (class != stx->ref.nil);
class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class);
class_obj->superclass = (p->superclass == QSE_NULL)?
stx->nil: qse_stx_lookup_class(stx,p->superclass);
class_obj = (qse_stx_class_t*)PTRBYREF(stx,class);
if (p->superclass)
{
class_obj->superclass = qse_stx_findclass(stx,p->superclass);
QSE_ASSERT (class_obj->superclass != stx->ref.nil);
}
nfields = 0; nfields = 0;
if (p->superclass != QSE_NULL) { if (p->superclass)
{
qse_word_t meta; qse_word_t meta;
qse_stx_metaclass_t* meta_obj; qse_stx_metaclass_t* meta_obj;
superclass = qse_stx_lookup_class(stx,p->superclass); superclass = qse_stx_findclass (stx, p->superclass);
QSE_ASSERT (superclass != stx->nil); QSE_ASSERT (superclass != stx->ref.nil);
meta = class_obj->header.class; meta = class_obj->h._class;
meta_obj = (qse_stx_metaclass_t*)QSE_STX_OBJPTR(stx,meta); meta_obj = (qse_stx_metaclass_t*)PTRBYREF(stx,meta);
meta_obj->superclass = QSE_STX_CLASS(stx,superclass); meta_obj->superclass = OBJCLASS(stx,superclass);
meta_obj->instance_class = class; meta_obj->instance_class = class;
while (superclass != stx->nil) { while (superclass != stx->ref.nil)
{
superclass_obj = (qse_stx_class_t*) superclass_obj = (qse_stx_class_t*)
QSE_STX_OBJPTR(stx,superclass); QSE_STX_OBJPTR(stx,superclass);
nfields += nfields +=
@ -327,13 +344,14 @@ static void make_intrinsic_classes (qse_stx_t* stx)
QSE_STX_SPEC_INDEXABLE_BITS; QSE_STX_SPEC_INDEXABLE_BITS;
superclass = superclass_obj->superclass; superclass = superclass_obj->superclass;
} }
} }
if (p->instance_variables != QSE_NULL) { if (p->instance_variables)
{
nfields += __count_names (p->instance_variables); nfields += __count_names (p->instance_variables);
class_obj->variables = class_obj->variables =
__new_string (stx, p->instance_variables); new_string (stx, p->instance_variables);
if (class_obj->variables == stx->ref.nil) return -1;
} }
QSE_ASSERT (nfields <= 0 || (nfields > 0 && QSE_ASSERT (nfields <= 0 || (nfields > 0 &&
@ -346,7 +364,7 @@ static void make_intrinsic_classes (qse_stx_t* stx)
for (p = class_info; p->name != QSE_NULL; p++) for (p = class_info; p->name != QSE_NULL; p++)
{ {
class = qse_stx_lookup_class(stx, p->name); class = qse_stx_lookup_class(stx, p->name);
QSE_ASSERT (class != stx->nil); QSE_ASSERT (class != stx->ref.nil);
class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class); class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class);
@ -373,7 +391,7 @@ static void make_intrinsic_classes (qse_stx_t* stx)
__set_subclasses (stx, QSE_STX_DATA(stx,array), p->name); __set_subclasses (stx, QSE_STX_DATA(stx,array), p->name);
class = qse_stx_lookup_class(stx, p->name); class = qse_stx_lookup_class(stx, p->name);
QSE_ASSERT (class != stx->nil); QSE_ASSERT (class != stx->ref.nil);
class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class); class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class);
class_obj->subclasses = array; class_obj->subclasses = array;
} }
@ -386,11 +404,13 @@ static void make_intrinsic_classes (qse_stx_t* stx)
__set_metaclass_subclasses (stx, QSE_STX_DATA(stx,array), p->name); __set_metaclass_subclasses (stx, QSE_STX_DATA(stx,array), p->name);
class = qse_stx_lookup_class(stx, p->name); class = qse_stx_lookup_class(stx, p->name);
QSE_ASSERT (class != stx->nil); QSE_ASSERT (class != stx->ref.nil);
metaclass = QSE_STX_CLASS(stx,class); metaclass = QSE_STX_CLASS(stx,class);
metaclass_obj = (qse_stx_metaclass_t*)QSE_STX_OBJPTR(stx, metaclass); metaclass_obj = (qse_stx_metaclass_t*)QSE_STX_OBJPTR(stx, metaclass);
metaclass_obj->subclasses = array; metaclass_obj->subclasses = array;
} }
return 0;
} }
static qse_word_t __count_names (const qse_char_t* str) static qse_word_t __count_names (const qse_char_t* str)
@ -456,7 +476,7 @@ static void __set_subclasses (
if (p->superclass == QSE_NULL) continue; if (p->superclass == QSE_NULL) continue;
if (qse_strcmp (str, p->superclass) != 0) continue; if (qse_strcmp (str, p->superclass) != 0) continue;
class = qse_stx_lookup_class (stx, p->name); class = qse_stx_lookup_class (stx, p->name);
QSE_ASSERT (class != stx->nil); QSE_ASSERT (class != stx->ref.nil);
array[n++] = class; array[n++] = class;
} }
} }
@ -471,7 +491,7 @@ static void __set_metaclass_subclasses (
if (p->superclass == QSE_NULL) continue; if (p->superclass == QSE_NULL) continue;
if (qse_strcmp (str, p->superclass) != 0) continue; if (qse_strcmp (str, p->superclass) != 0) continue;
class = qse_stx_lookup_class (stx, p->name); class = qse_stx_lookup_class (stx, p->name);
QSE_ASSERT (class != stx->nil); QSE_ASSERT (class != stx->ref.nil);
array[n++] = QSE_STX_CLASS(stx,class); array[n++] = QSE_STX_CLASS(stx,class);
} }
} }
@ -484,7 +504,7 @@ static qse_word_t __make_classvar_dict (
const qse_char_t* name; const qse_char_t* name;
dict = qse_stx_instantiate ( dict = qse_stx_instantiate (
stx, stx->class_system_dictionary, stx, stx->class_systemdictionary,
QSE_NULL, QSE_NULL, __count_names(names)); QSE_NULL, QSE_NULL, __count_names(names));
do { do {
@ -498,7 +518,7 @@ static qse_word_t __make_classvar_dict (
*p != QSE_T('\0')) p++; *p != QSE_T('\0')) p++;
symbol = qse_stx_new_symbolx (stx, name, p - name); symbol = qse_stx_new_symbolx (stx, name, p - name);
qse_stx_dict_put (stx, dict, symbol, stx->nil); qse_stx_dict_put (stx, dict, symbol, stx->ref.nil);
} while (1); } while (1);
return dict; return dict;
@ -518,7 +538,7 @@ static int sketch_nil (qse_stx_t* stx)
{ {
qse_stx_objidx_t idx; qse_stx_objidx_t idx;
qse_word_t ref; qse_word_t ref;
qse_stx_wordobjptr_t ptr; qse_stx_wordobj_t* ptr;
/* nil contains no member fields. allocate space for /* nil contains no member fields. allocate space for
* an object header */ * an object header */
@ -526,7 +546,7 @@ static int sketch_nil (qse_stx_t* stx)
if (idx == QSE_STX_OBJIDX_INVALID) return -1; if (idx == QSE_STX_OBJIDX_INVALID) return -1;
ref = IDXTOREF(stx,idx); ref = IDXTOREF(stx,idx);
ptr = (qse_stx_wordobjptr_t)PTRBYIDX(stx,idx); ptr = (qse_stx_wordobj_t*)PTRBYIDX(stx,idx);
/* store the nil reference first */ /* store the nil reference first */
stx->ref.nil = ref; stx->ref.nil = ref;
@ -536,7 +556,7 @@ static int sketch_nil (qse_stx_t* stx)
ptr->h._type = QSE_STX_WORDOBJ; ptr->h._type = QSE_STX_WORDOBJ;
ptr->h._mark = 0; ptr->h._mark = 0;
ptr->h._refcnt = 0; ptr->h._refcnt = 0;
ptr->h._size = 0; ptr->h._size = 0;
ptr->h._class = stx->ref.nil; /* the class is yet to be set */ ptr->h._class = stx->ref.nil; /* the class is yet to be set */
ptr->h._backref = ref; ptr->h._backref = ref;
@ -548,14 +568,28 @@ static int sketch_nil (qse_stx_t* stx)
if ((var) == (stx)->ref.nil) return -1; \ if ((var) == (stx)->ref.nil) return -1; \
) )
#define ADD_TO_SYSDIC(stx,key,value) QSE_BLOCK (\
if (qse_stx_putdic ((stx), (stx)->ref.sysdic, (key), (value)) == (stx)->ref.nil) return -1; \
)
#define NEW_SYMBOL_TO(stx,var,name) QSE_BLOCK (\
var = qse_stx_newsymbol ((stx), name); \
if (var == (stx)->ref.nil) return -1; \
)
#define NEW_CLASS_TO(stx,var,name) QSE_BLOCK (\
var = qse_stx_newclass ((stx), name); \
if (var == (stx)->ref.nil) return -1; \
)
static int sketch_key_objects (qse_stx_t* stx) static int sketch_key_objects (qse_stx_t* stx)
{ {
qse_word_t class_SymbolMeta; qse_word_t class_SymbolMeta;
qse_word_t class_MetaclassMeta; qse_word_t class_MetaclassMeta;
qse_word_t class_AssociationMeta; qse_word_t class_AssociationMeta;
qse_word_t symbol_Symbol; qse_word_t symbol_symbol;
qse_word_t symbol_Metaclass; qse_word_t symbol_metaclass;
qse_word_t symbol_Association; qse_word_t symbol_association;
/* allocate true and false. the class pointer is not correct yet */ /* allocate true and false. the class pointer is not correct yet */
ALLOC_WORDOBJ_TO (stx, stx->ref.true, 0, 0); ALLOC_WORDOBJ_TO (stx, stx->ref.true, 0, 0);
@ -563,13 +597,13 @@ static int sketch_key_objects (qse_stx_t* stx)
/* create a symbol table partially initialized */ /* create a symbol table partially initialized */
/* TODO: initial symbol table size */ /* TODO: initial symbol table size */
ALLOC_WORDOBJ_TO (stx, stx->ref.symtab, 1, 256); ALLOC_WORDOBJ_TO (stx, stx->ref.symtab, 1, SYMTAB_INIT_CAPA);
/* set tally to 0. */ /* set tally to 0. */
WORDAT(stx,stx->ref.symtab,QSE_STX_SYMTAB_TALLY) = INTTOREF(stx,0); WORDAT(stx,stx->ref.symtab,QSE_STX_SYMTAB_TALLY) = INTTOREF(stx,0);
/* global system dictionary */ /* global system dictionary */
/* TODO: initial dictionary size */ /* TODO: initial dictionary size */
ALLOC_WORDOBJ_TO (stx, stx->ref.sysdic, 1, 256); ALLOC_WORDOBJ_TO (stx, stx->ref.sysdic, 1, SYSDIC_INIT_CAPA);
/* set tally to 0 */ /* set tally to 0 */
WORDAT(stx,stx->ref.sysdic,QSE_STX_DIC_TALLY) = INTTOREF(stx,0); WORDAT(stx,stx->ref.sysdic,QSE_STX_DIC_TALLY) = INTTOREF(stx,0);
@ -619,39 +653,49 @@ static int sketch_key_objects (qse_stx_t* stx)
* class_symbol are set later in make_builtin_classes */ * class_symbol are set later in make_builtin_classes */
/* #Symbol */ /* #Symbol */
symbol_Symbol = qse_stx_newsymbol ( NEW_SYMBOL_TO (stx, symbol_symbol, QSE_T("Symbol"));
stx, stx->ref.symtab, QSE_T("Symbol"));
/* #Metaclass */ /* #Metaclass */
symbol_Metaclass = qse_stx_newsymbol ( NEW_SYMBOL_TO (stx, symbol_metaclass, QSE_T("Metaclass"));
stx, stx->ref.symtab, QSE_T("Metaclass"));
/* #Association */ /* #Association */
symbol_Association = qse_stx_newsymbol ( NEW_SYMBOL_TO (stx, symbol_association, QSE_T("Association"));
stx, stx->ref.symtab, QSE_T("Association"));
/* Symbol setName: #Symbol */ /* Symbol setName: #Symbol */
WORDAT(stx,stx->ref.class_symbol,QSE_STX_CLASS_NAME) = symbol_Symbol; WORDAT(stx,stx->ref.class_symbol,QSE_STX_CLASS_NAME) = symbol_symbol;
/* Metaclass setName: #Metaclass */ /* Metaclass setName: #Metaclass */
WORDAT(stx,stx->ref.class_metaclass,QSE_STX_CLASS_NAME) = symbol_Metaclass; WORDAT(stx,stx->ref.class_metaclass,QSE_STX_CLASS_NAME) = symbol_metaclass;
/* Association setName: #Association */ /* Association setName: #Association */
WORDAT(stx,stx->ref.class_association,QSE_STX_CLASS_NAME) = symbol_Association; WORDAT(stx,stx->ref.class_association,QSE_STX_CLASS_NAME) = symbol_association;
#if 0
/* register class names into the system dictionary */ /* register class names into the system dictionary */
qse_stx_dict_put (stx, ADD_TO_SYSDIC (stx, symbol_symbol, stx->ref.class_symbol);
stx->ref.sysdic, symbol_Symbol, stx->class_symbol); ADD_TO_SYSDIC (stx, symbol_metaclass, stx->ref.class_metaclass);
qse_stx_dict_put (stx, ADD_TO_SYSDIC (stx, symbol_association, stx->ref.class_association);
stx->ref.sysdic, symbol_Metaclass, stx->class_metaclass);
qse_stx_dict_put (stx,
stx->ref.sysdic, symbol_Association, stx->class_association);
#endif
return 0; return 0;
} }
int make_key_classes (qse_stx_t* stx)
{
/* object, class, and array are precreated for easier instantiation
* of intrinsic classes */
NEW_CLASS_TO (stx, stx->ref.class_object, QSE_T("Object"));
NEW_CLASS_TO (stx, stx->ref.class_class, QSE_T("Class"));
NEW_CLASS_TO (stx, stx->ref.class_array, QSE_T("Array"));
NEW_CLASS_TO (stx, stx->ref.class_bytearray, QSE_T("ByteArray"));
NEW_CLASS_TO (stx, stx->ref.class_string, QSE_T("String"));
NEW_CLASS_TO (stx, stx->ref.class_character, QSE_T("Character"));
NEW_CLASS_TO (stx, stx->ref.class_context, QSE_T("Context"));
NEW_CLASS_TO (stx, stx->ref.class_systemsymboltable, QSE_T("SystemSymbolTable"));
NEW_CLASS_TO (stx, stx->ref.class_systemdictionary, QSE_T("SystemDictionary"));
NEW_CLASS_TO (stx, stx->ref.class_method, QSE_T("Method"));
NEW_CLASS_TO (stx, stx->ref.class_smallinteger, QSE_T("SmallInteger"));
return 0;
}
int qse_stx_boot (qse_stx_t* stx) int qse_stx_boot (qse_stx_t* stx)
{ {
qse_word_t symbol_Smalltalk; qse_word_t symbol_smalltalk;
qse_word_t object_meta; qse_word_t object_meta;
/* create a partially initialized nil object for bootstrapping */ /* create a partially initialized nil object for bootstrapping */
@ -660,29 +704,13 @@ int qse_stx_boot (qse_stx_t* stx)
/* continue intializing other key objects */ /* continue intializing other key objects */
if (sketch_key_objects (stx) <= -1) goto oops; if (sketch_key_objects (stx) <= -1) goto oops;
if (make_key_classes (stx) <= -1) goto oops;
if (make_intrisic_classes (stx) <= -1) goto oops;
return 0; return 0;
#if 0 #if 0
__create_bootstrapping_objects (stx);
/* object, class, and array are precreated for easier instantiation
* of builtin classes */
stx->class_object = qse_stx_newclass (stx, QSE_T("Object"));
stx->class_class = qse_stx_newclass (stx, QSE_T("Class"));
stx->class_array = qse_stx_newclass (stx, QSE_T("Array"));
stx->class_bytearray = qse_stx_newclass (stx, QSE_T("ByteArray"));
stx->class_string = qse_stx_newclass (stx, QSE_T("String"));
stx->class_character = qse_stx_newclass (stx, QSE_T("Character"));
stx->class_context = qse_stx_newclass (stx, QSE_T("Context"));
stx->class_system_dictionary =
qse_stx_newclass (stx, QSE_T("SystemDictionary"));
stx->class_method =
qse_stx_newclass (stx, QSE_T("Method"));
stx->class_smallinteger =
qse_stx_newclass (stx, QSE_T("SmallInteger"));
make_intrisic_classes (stx);
/* (Object class) setSuperclass: Class */ /* (Object class) setSuperclass: Class */
object_meta = QSE_STX_CLASS(stx,stx->class_object); object_meta = QSE_STX_CLASS(stx,stx->class_object);
QSE_STX_WORD_AT(stx,object_meta,QSE_STX_METACLASS_SUPERCLASS) = stx->class_class; QSE_STX_WORD_AT(stx,object_meta,QSE_STX_METACLASS_SUPERCLASS) = stx->class_class;
@ -699,25 +727,21 @@ int qse_stx_boot (qse_stx_t* stx)
} }
/* more initialization */ /* more initialization */
QSE_STX_CLASS(stx,stx->sysdic) = stx->class_system_dictionary; OBJCLASS(stx,stx->ref.sysdic) = stx->class_systemdictionary;
NEW_SYMBOL_TO (stx, symbol_smalltalk, QSE_T("Smalltalk"));
symbol_Smalltalk = qse_stx_new_symbol (stx, QSE_T("Smalltalk")); ADD_TO_SYSDIC (stx, symbol_smalltalk, stx->ref.sysdic);
qse_stx_dict_put (stx, stx->sysdic, symbol_Smalltalk, stx->sysdic);
/* create #nil, #true, #false */ /* create #nil, #true, #false */
qse_stx_new_symbol (stx, QSE_T("nil")); NEW_SYMBOL_TO (stx, symbol_nil, QSE_T("nil"));
qse_stx_new_symbol (stx, QSE_T("true")); NEW_SYMBOL_TO (stx, symbol_true, QSE_T("true"));
qse_stx_new_symbol (stx, QSE_T("false")); NEW_SYMBOL_TO (stx, symbol_false, QSE_T("false"));
/* nil setClass: UndefinedObject */ /* nil setClass: UndefinedObject */
QSE_STX_CLASS(stx,stx->nil) = OBJCLASS(stx,stx->ref.nil) = qse_stx_findclass (stx, QSE_T("UndefinedObject"));
qse_stx_lookup_class(stx, QSE_T("UndefinedObject"));
/* true setClass: True */ /* true setClass: True */
QSE_STX_CLASS(stx,stx->true) = OBJCLASS(stx,stx->ref.true) = qse_stx_findclass (stx, QSE_T("True"));
qse_stx_lookup_class (stx, QSE_T("True"));
/* fales setClass: False */ /* fales setClass: False */
QSE_STX_CLASS(stx,stx->false) = OBJCLASS(stx,stx->ref.false) = qse_stx_findclass (stx, QSE_T("False"));
qse_stx_lookup_class (stx, QSE_T("False"));
__filein_kernel (stx); __filein_kernel (stx);
return 0; return 0;

View File

@ -32,11 +32,11 @@ qse_word_t qse_stx_newclass (qse_stx_t* stx, const qse_char_t* name)
return class; return class;
} }
qse_word_t qse_stx_lookup_class (qse_stx_t* stx, const qse_char_t* name) qse_word_t qse_stx_findclass (qse_stx_t* stx, const qse_char_t* name)
{ {
qse_word_t assoc, meta, value; qse_word_t assoc, meta, value;
assoc = qse_stx_dict_lookup (stx, stx->smalltalk, name); assoc = qse_stx_dict_lookup (stx, stx->ref.sysdic, name);
if (assoc == stx->nil) if (assoc == stx->nil)
{ {
return stx->nil; return stx->nil;
@ -44,7 +44,7 @@ qse_word_t qse_stx_lookup_class (qse_stx_t* stx, const qse_char_t* name)
value = QSE_STX_WORD_AT(stx,assoc,QSE_STX_ASSOCIATION_VALUE); value = QSE_STX_WORD_AT(stx,assoc,QSE_STX_ASSOCIATION_VALUE);
meta = QSE_STX_CLASS(stx,value); meta = QSE_STX_CLASS(stx,value);
if (QSE_STX_CLASS(stx,meta) != stx->class_metaclass) return stx->nil; if (QSE_STX_CLASS(stx,meta) != stx->ref.class_metaclass) return stx->nil;
return value; return value;
} }
@ -167,3 +167,67 @@ qse_word_t qse_stx_lookup_method (qse_stx_t* stx,
return stx->nil; return stx->nil;
} }
qse_word_t qse_stx_instantiate (
qse_stx_t* stx, qse_word_t classref, void* data,
const void* variable_data, qse_word_t variable_nflds)
{
qse_stx_class_t* classptr;
qse_word_t spec, nflds, inst;
int variable;
QSE_ASSERT (REFISIDX(stx,classref));
/* don't instantiate a metaclass whose instance must be
created in a different way */
QSE_ASSERT (OBJCLASS(stx,classref) != stx->ref.class_metaclass);
classptr = (qse_stx_class_t*) PTRBYRFF (stx, classref);
/* TODO: maybe delete the following line */
QSE_ASSERT (QSE_STX_CLASS(class) != stx->class_metaclass);
QSE_ASSERT (REFISINT(stx,classptr->spec));
spec = REFTOINT(classptr->spec);
nflds = (spec >> SPEC_VARIABLE_BITS);
variable = spec & SPEC_VARIABLE_MASK;
switch (variable)
{
case SPEC_VARIABLE_BYTE:
/* variable-size byte class */
QSE_ASSERT (nflds == 0 && data == QSE_NULL);
inst = qse_stx_allocbyteobj(
stx, variable_data, variable_nflds);
break;
case SPEC_VARIABLE_CHAR:
/* variable-size char class */
QSE_ASSERT (nflds == 0 && data == QSE_NULL);
inst = qse_stx_alloccharobj (
stx, variable_data, variable_nflds);
break;
case SPEC_VARIABLE_WORD:
/* variable-size class */
inst = qse_stx_allocwordobj (
stx, data, nflds, variable_data, variable_nflds);
break;
case SPEC_FIXED_WORD:
/* fixed size */
QSE_ASSERT (variable_nflds == 0 && variable_data == QSE_NULL);
inst = qse_stx_allocwordobj (
stx, data, nflds, QSE_NULL, 0);
break;
default:
/* this should never happen */
QSE_ASSERTX (0, "this should never happen");
qse_stx_seterror
inst = stx->ref.nil;
}
if (inst != stx->ref.nil) OBJCLASS(stx,inst) = classref;
return inst;
}

View File

@ -66,9 +66,15 @@ typedef struct qse_stx_metaclass_t qse_stx_metaclass_t;
extern "C" { extern "C" {
#endif #endif
qse_word_t qse_stx_new_class (qse_stx_t* stx, const qse_char_t* name); qse_word_t qse_stx_newclass (
qse_stx_t* stx,
const qse_char_t* name
);
qse_word_t qse_stx_lookup_class (qse_stx_t* stx, const qse_char_t* name); qse_word_t qse_stx_lookupclass (
qse_stx_t* stx,
const qse_char_t* name
);
int qse_stx_get_instance_variable_index ( int qse_stx_get_instance_variable_index (
qse_stx_t* stx, qse_word_t class_index, qse_stx_t* stx, qse_word_t class_index,
@ -79,6 +85,16 @@ qse_word_t qse_stx_lookup_class_variable (
qse_word_t qse_stx_lookup_method (qse_stx_t* stx, qse_word_t qse_stx_lookup_method (qse_stx_t* stx,
qse_word_t class_index, const qse_char_t* name, qse_bool_t from_super); qse_word_t class_index, const qse_char_t* name, qse_bool_t from_super);
qse_word_t qse_stx_instantiate (
qse_stx_t* stx,
qse_word_t classref,
const void* data,
const void* variable_data,
qse_word_t variable_nfields
);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

272
qse/lib/stx/cls.c Normal file
View File

@ -0,0 +1,272 @@
/*
* $Id: class.c 118 2008-03-03 11:21:33Z baconevi $
*/
#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;
qse_word_t class_name;
QSE_ASSERT (REFISIDX(stx,stx->ref.class_metaclass));
meta = qse_stx_allocwordobj (
stx, QSE_NULL, QSE_STX_METACLASS_SIZE, QSE_NULL, 0);
if (meta == stx->ref.nil) return stx->ref.nil;
OBJCLASS(stx,meta) = stx->ref.class_metaclass;
/* 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));
/* the spec of the class is set later in __create_builtin_classes */
class = qse_stx_allocwordobj (
stx, QSE_NULL, QSE_STX_CLASS_SIZE, QSE_NULL, 0);
OBJCLASS(stx,class) = meta;
class_name = qse_stx_newsymbol (stx, name);
if (class_name == stx->ref.nil) return stx->ref.nil;
WORDAT(stx,class,QSE_STX_CLASS_NAME) = class_name;
return (qse_stx_putdic (stx, stx->ref.sysdic, class_name, class) == stx->ref.nil)? stx->ref.nil: class;
}
qse_word_t qse_stx_findclass (qse_stx_t* stx, const qse_char_t* name)
{
qse_word_t assoc, meta, value;
/* look up the system dictionary for the name given */
assoc = qse_stx_lookupdic (stx, stx->ref.sysdic, name);
if (assoc == stx->ref.nil)
{
/*qse_stx_seterrnum (stx, QSE_STX_ENOCLASS, QSE_NULL);*/
return stx->ref.nil;
}
/* get the value part in the association for the name */
value = WORDAT(stx,assoc,QSE_STX_ASSOC_VALUE);
/* check if its class is Metaclass because the class of
* a class object must be Metaclass. */
meta = OBJCLASS(stx,value);
if (OBJCLASS(stx,meta) != stx->ref.class_metaclass)
{
/*qse_stx_seterrnum (stx, QSE_STX_ENOTCLASS, QSE_NULL);*/
return stx->ref.nil;
}
return value;
}
#if 0
int qse_stx_get_instance_variable_index (
qse_stx_t* stx, qse_word_t class_index,
const qse_char_t* name, qse_word_t* index)
{
qse_word_t index_super = 0;
qse_stx_class_t* class_obj;
qse_stx_char_object_t* string;
class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class_index);
qse_assert (class_obj != QSE_NULL);
if (class_obj->superclass != stx->nil) {
if (qse_stx_get_instance_variable_index (
stx, class_obj->superclass, name, &index_super) == 0) {
*index = index_super;
return 0;
}
}
if (class_obj->header.class == stx->class_metaclass) {
/* metaclass */
/* TODO: can a metaclas have instance variables? */
*index = index_super;
}
else {
if (class_obj->variables == stx->nil) *index = 0;
else {
string = QSE_STX_CHAR_OBJECT(stx, class_obj->variables);
if (qse_stx_strword(string->data, name, index) != QSE_NULL) {
*index += index_super;
return 0;
}
}
*index += index_super;
}
return -1;
}
qse_word_t qse_stx_lookup_class_variable (
qse_stx_t* stx, qse_word_t class_index, const qse_char_t* name)
{
qse_stx_class_t* class_obj;
class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class_index);
qse_assert (class_obj != QSE_NULL);
if (class_obj->superclass != stx->nil) {
qse_word_t tmp;
tmp = qse_stx_lookup_class_variable (
stx, class_obj->superclass, name);
if (tmp != stx->nil) return tmp;
}
/* TODO: can a metaclas have class variables? */
if (class_obj->header.class != stx->class_metaclass &&
class_obj->class_variables != stx->nil) {
if (qse_stx_dict_lookup(stx,
class_obj->class_variables,name) != stx->nil) return class_index;
}
return stx->nil;
}
qse_word_t qse_stx_lookup_method (qse_stx_t* stx,
qse_word_t class_index, const qse_char_t* name, qse_bool_t from_super)
{
qse_stx_class_t* class_obj;
class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class_index);
qse_assert (class_obj != QSE_NULL);
#if 0
if (class_obj->header.class != stx->class_metaclass &&
class_obj->methods != stx->nil) {
qse_word_t assoc;
assoc = qse_stx_dict_lookup(stx, class_obj->methods, name);
if (assoc != stx->nil) {
qse_assert (QSE_STX_CLASS(stx,assoc) == stx->class_association);
return QSE_STX_WORD_AT(stx, assoc, QSE_STX_ASSOCIATION_VALUE);
}
}
if (class_obj->superclass != stx->nil) {
qse_word_t tmp;
tmp = qse_stx_lookup_method (
stx, class_obj->superclass, name);
if (tmp != stx->nil) return tmp;
}
#endif
while (class_index != stx->nil) {
class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class_index);
qse_assert (class_obj != QSE_NULL);
qse_assert (
class_obj->header.class == stx->class_metaclass ||
QSE_STX_CLASS(stx,class_obj->header.class) == stx->class_metaclass);
if (from_super) {
from_super = qse_false;
}
else if (class_obj->methods != stx->nil) {
qse_word_t assoc;
assoc = qse_stx_dict_lookup(stx, class_obj->methods, name);
if (assoc != stx->nil) {
qse_assert (QSE_STX_CLASS(stx,assoc) == stx->class_association);
return QSE_STX_WORD_AT(stx, assoc, QSE_STX_ASSOCIATION_VALUE);
}
}
class_index = class_obj->superclass;
}
return stx->nil;
}
#endif
qse_word_t qse_stx_instantiate (
qse_stx_t* stx, qse_word_t classref, const void* data,
const void* variable_data, qse_word_t variable_nflds)
{
qse_stx_class_t* classptr;
qse_word_t spec, nflds, inst;
int variable;
QSE_ASSERT (REFISIDX(stx,classref));
/* don't instantiate a metaclass whose instance must be
created in a different way */
QSE_ASSERT (OBJCLASS(stx,classref) != stx->ref.class_metaclass);
classptr = (qse_stx_class_t*)PTRBYREF(stx,classref);
QSE_ASSERT (REFISINT(stx,classptr->spec));
spec = REFTOINT(stx,classptr->spec);
nflds = (spec >> SPEC_VARIABLE_BITS);
variable = spec & SPEC_VARIABLE_MASK;
switch (variable)
{
case SPEC_VARIABLE_BYTE:
/* variable-size byte class */
QSE_ASSERT (nflds == 0 && data == QSE_NULL);
inst = qse_stx_allocbyteobj (
stx, variable_data, variable_nflds);
break;
case SPEC_VARIABLE_CHAR:
/* variable-size char class */
QSE_ASSERT (nflds == 0 && data == QSE_NULL);
inst = qse_stx_alloccharobj (
stx, variable_data, variable_nflds);
break;
case SPEC_VARIABLE_WORD:
/* variable-size class */
inst = qse_stx_allocwordobj (
stx, data, nflds, variable_data, variable_nflds);
break;
case SPEC_FIXED_WORD:
/* fixed size */
QSE_ASSERT (variable_nflds == 0 && variable_data == QSE_NULL);
inst = qse_stx_allocwordobj (
stx, data, nflds, QSE_NULL, 0);
break;
default:
/* this should never happen */
QSE_ASSERTX (0, "this should never happen");
qse_stx_seterrnum (stx, QSE_STX_EINTERN, QSE_NULL);
return stx->ref.nil;
}
QSE_ASSERT (inst != stx->ref.nil);
OBJCLASS(stx,inst) = classref;
return inst;
}

75
qse/lib/stx/cls.h Normal file
View File

@ -0,0 +1,75 @@
/*
* $Id$
*/
#ifndef _QSE_LIB_STX_CLS_H_
#define _QSE_LIB_STX_CLS_H_
#define QSE_STX_CLASS_SIZE 8
#define QSE_STX_CLASS_SPEC 0
#define QSE_STX_CLASS_METHODS 1
#define QSE_STX_CLASS_SUPERCLASS 2
#define QSE_STX_CLASS_SUBCLASSES 3
#define QSE_STX_CLASS_NAME 4
#define QSE_STX_CLASS_VARIABLES 5
#define QSE_STX_CLASS_CLASS_VARIABLES 6
#define QSE_STX_CLASS_POOL_DICTIONARIES 7
#define QSE_STX_METACLASS_SIZE 5
#define QSE_STX_METACLASS_SPEC 0
#define QSE_STX_METACLASS_METHODS 1
#define QSE_STX_METACLASS_SUPERCLASS 2
#define QSE_STX_METACLASS_SUBCLASSES 3
#define QSE_STX_METACLASS_INSTANCE_CLASS 4
#define SPEC_VARIABLE_BITS 2
#define SPEC_VARIABLE_MASK 0x03
#define SPEC_FIXED_WORD 0x00
#define SPEC_VARIABLE_WORD 0x01
#define SPEC_VARIABLE_BYTE 0x02
#define SPEC_VARIABLE_CHAR 0x03
#define MAKE_SPEC(nflds,variable) \
(((nflds) << SPEC_VARIABLE_BITS) | (variable))
#ifdef __cplusplus
extern "C" {
#endif
qse_word_t qse_stx_newclass (
qse_stx_t* stx,
const qse_char_t* name
);
qse_word_t qse_stx_findclass (
qse_stx_t* stx,
const qse_char_t* name
);
#if 0
int qse_stx_get_instance_variable_index (
qse_stx_t* stx, qse_word_t class_index,
const qse_char_t* name, qse_word_t* index);
qse_word_t qse_stx_lookup_class_variable (
qse_stx_t* stx, qse_word_t class_index, const qse_char_t* name);
qse_word_t qse_stx_lookup_method (qse_stx_t* stx,
qse_word_t class_index, const qse_char_t* name, qse_bool_t from_super);
#endif
qse_word_t qse_stx_instantiate (
qse_stx_t* stx,
qse_word_t classref,
const void* data,
const void* variable_data,
qse_word_t variable_nfields
);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -44,45 +44,40 @@ static qse_word_t new_assoc (
return x; return x;
} }
static qse_word_t grow_dic (qse_stx_t* stx, qse_word_t dic) static qse_word_t expand (qse_stx_t* stx, qse_word_t dic)
{ {
qse_word_t new, size, index, assoc; qse_word_t newref, size, index, assoc;
/* WARNING: /* WARNING:
* if this assertion fails, adjust the initial size of the * if this assertion fails, adjust the initial size of the
* system dicionary. i don't want this function to be called * system dicionary. i don't want this function to be called
* during the bootstrapping. * during the bootstrapping.
*/ */
QSE_ASSERT (stx->ref.class_system_dictionary != stx->ref.nil); QSE_ASSERT (stx->ref.class_systemdictionary != stx->ref.nil);
QSE_ASSERT (REFISIDX(stx,dic)); QSE_ASSERT (REFISIDX(stx,dic));
QSE_ASSERT (OBJCLASS(stx,dic) == stx->ref.class_system_dictionary); QSE_ASSERT (OBJCLASS(stx,dic) == stx->ref.class_systemdictionary);
size = OBJSIZE(stx,dic); size = OBJSIZE(stx,dic);
new = qse_stx_instantiate (stx, newref = qse_stx_instantiate (stx,
OBJCLASS(stx,dic), QSE_NULL, QSE_NULL, (size - 1) * 2); OBJCLASS(stx,dic), QSE_NULL, QSE_NULL, (size - 1) * 2);
if (new == stx->ref.nil) return stx->ref.nil; if (newref == stx->ref.nil) return stx->ref.nil;
WORDAT(stx,new,QSE_STX_DIC_TALLY) = INTTOREF (stx, 0); WORDAT(stx,newref,QSE_STX_DIC_TALLY) = INTTOREF (stx, 0);
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->ref.nil) continue; if (assoc == stx->ref.nil) continue;
qse_stx_putdic (stx, new, if (qse_stx_putdic (stx, newref,
WORDAT(stx,assoc,QSE_STX_ASSOC_KEY), WORDAT(stx,assoc,QSE_STX_ASSOC_KEY),
WORDAT(stx,assoc,QSE_STX_ASSOC_VALUE)); WORDAT(stx,assoc,QSE_STX_ASSOC_VALUE)) == stx->ref.nil)
{
return stx->ref.nil;
}
} }
/* TODO: explore if dic can be immediately destroyed. */ /* TODO: explore if dic can be immediately destroyed. */
qse_stx_swapmem (stx, REFTOIDX(stx,dic), REFTOIDX(stx,newref));
QSE_ASSERT (QSE_SIZEOF(qse_stx_object_t*) == QSE_SIZEOF(qse_uint_t));
QSE_SWAP (
PTRBYIDX(stx,dic),
PTRBYIDX(stx,new),
qse_stx_object_t*,
qse_uint_t
);
return dic; return dic;
} }
@ -97,7 +92,7 @@ static qse_word_t find_slot (
QSE_ASSERT (REFISIDX(stx,dic)); QSE_ASSERT (REFISIDX(stx,dic));
QSE_ASSERT (OBJTYPE(stx,dic) == WORDOBJ); QSE_ASSERT (OBJTYPE(stx,dic) == WORDOBJ);
QSE_ASSERT (dic == stx->ref.sysdic || QSE_ASSERT (dic == stx->ref.sysdic ||
OBJCLASS(stx,key) == stx->ref.class_system_dictionary); OBJCLASS(stx,key) == stx->ref.class_systemdictionary);
/* ensure that the key is a symbol */ /* ensure that the key is a symbol */
QSE_ASSERT (REFISIDX(stx,key)); QSE_ASSERT (REFISIDX(stx,key));
@ -145,7 +140,7 @@ qse_word_t qse_stx_lookupdic (
QSE_ASSERT (REFISIDX(stx,dic)); QSE_ASSERT (REFISIDX(stx,dic));
QSE_ASSERT (OBJTYPE(stx,dic) == WORDOBJ); QSE_ASSERT (OBJTYPE(stx,dic) == WORDOBJ);
QSE_ASSERT (dic == stx->ref.sysdic || QSE_ASSERT (dic == stx->ref.sysdic ||
OBJCLASS(stx,dic) == stx->ref.class_system_dictionary); OBJCLASS(stx,dic) == stx->ref.class_systemdictionary);
capa = OBJSIZE(stx,dic) - 1; /* exclude the tally field */ capa = OBJSIZE(stx,dic) - 1; /* exclude the tally field */
hash = qse_stx_hashstr (stx, skey) % capa; hash = qse_stx_hashstr (stx, skey) % capa;
@ -210,7 +205,7 @@ qse_word_t qse_stx_putdic (
* - make sure that lookup never enters a infinite loop. * - make sure that lookup never enters a infinite loop.
* - the slot's index can be returned when no key is found. * - 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 (expand (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));

View File

@ -9,7 +9,7 @@
#define QSE_STX_ASSOC_KEY 0 #define QSE_STX_ASSOC_KEY 0
#define QSE_STX_ASSOC_VALUE 1 #define QSE_STX_ASSOC_VALUE 1
/* The SystemDictionary is a word variable class. /* The SystemDictionary is a variable word class.
* The info below is for the fixed part only */ * The info below is for the fixed part only */
#define QSE_STX_DIC_SIZE 1 #define QSE_STX_DIC_SIZE 1
#define QSE_STX_DIC_TALLY 0 #define QSE_STX_DIC_TALLY 0

View File

@ -5,7 +5,7 @@
#include "stx.h" #include "stx.h"
#include <qse/cmn/str.h> #include <qse/cmn/str.h>
qse_word_t qse_stx_hashbyte (qse_stx_t* stx, const void* data, qse_word_t len) qse_word_t qse_stx_hashbytes (qse_stx_t* stx, const void* data, qse_word_t len)
{ {
qse_word_t h = 0; qse_word_t h = 0;
qse_byte_t* bp, * be; qse_byte_t* bp, * be;
@ -38,6 +38,54 @@ qse_word_t qse_stx_hashstrx (qse_stx_t* stx, const qse_char_t* str, qse_word_t l
return qse_stx_hashbytes (stx, str, len * QSE_SIZEOF(*str)); return qse_stx_hashbytes (stx, str, len * QSE_SIZEOF(*str));
} }
qse_word_t qse_stx_hashobj (qse_stx_t* stx, qse_word_t ref)
{
qse_word_t hv;
if (REFISINT(stx, ref))
{
qse_word_t tmp = REFTOINT(stx, ref);
hv = qse_stx_hashbytes (stx, &tmp, QSE_SIZEOF(tmp));
}
else
{
switch (OBJTYPE(stx,ref))
{
case BYTEOBJ:
hv = qse_stx_hashbytes (
stx,
&BYTEAT(stx,ref,0),
OBJSIZE(stx,ref)
);
break;
case CHAROBJ:
/* the additional null is not taken into account */
hv = qse_stx_hashbytes (
stx,
&CHARAT(stx,ref,0),
OBJSIZE(stx,ref) * QSE_SIZEOF(qse_char_t)
);
break;
case WORDOBJ:
hv = qse_stx_hashbytes (
stx,
&WORDAT(stx,ref,0),
OBJSIZE(stx,ref) * QSE_SIZEOF(qse_word_t)
);
break;
default:
QSE_ASSERT (
!"This should never happen"
);
break;
}
}
return hv;
}
#if 0 #if 0
qse_char_t* qse_stx_strword ( qse_char_t* qse_stx_strword (

View File

@ -26,6 +26,13 @@ qse_word_t qse_stx_hashstrx (
qse_word_t len qse_word_t len
); );
qse_word_t qse_stx_hashobj (
qse_stx_t* stx,
qse_word_t ref
);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -20,7 +20,11 @@ int qse_stx_initmem (qse_stx_t* stx, qse_size_t capa)
stx->mmgr, stx->mmgr,
capa * QSE_SIZEOF(*stx->mem.slot) capa * QSE_SIZEOF(*stx->mem.slot)
); );
if (stx->mem.slot == QSE_NULL) return -1; if (stx->mem.slot == QSE_NULL)
{
qse_stx_seterrnum (stx, QSE_STX_ENOMEM, QSE_NULL);
return -1;
}
stx->mem.capa = capa; stx->mem.capa = capa;
@ -59,7 +63,13 @@ qse_stx_objidx_t qse_stx_allocmem (qse_stx_t* stx, qse_size_t nbytes)
if (stx->mem.free == QSE_NULL) if (stx->mem.free == QSE_NULL)
{ {
qse_stx_gcmem (stx); qse_stx_gcmem (stx);
if (stx->mem.free == QSE_NULL) return QSE_STX_OBJIDX_INVALID; if (stx->mem.free == QSE_NULL)
{
/* ran out of object table slots */
/* TODO: NEED TO USE a different error code??? */
qse_stx_seterrnum (stx, QSE_STX_ENOMEM, QSE_NULL);
return QSE_STX_OBJIDX_INVALID;
}
} }
/* TODO: memory allocation by region.. instead of calling individual QSE_MMGR_ALLOC /* TODO: memory allocation by region.. instead of calling individual QSE_MMGR_ALLOC
@ -73,7 +83,8 @@ qse_stx_objidx_t qse_stx_allocmem (qse_stx_t* stx, qse_size_t nbytes)
objptr = (qse_stx_objptr_t) QSE_MMGR_ALLOC (stx->mmgr, nbytes); objptr = (qse_stx_objptr_t) QSE_MMGR_ALLOC (stx->mmgr, nbytes);
if (objptr == QSE_NULL) if (objptr == QSE_NULL)
{ {
QSE_ASSERT (QSE_T("MEMORY ALLOCATION ERROR\n") == QSE_NULL); /* ran out of object memory */
qse_stx_seterrnum (stx, QSE_STX_ENOMEM, QSE_NULL);
return QSE_STX_OBJIDX_INVALID; return QSE_STX_OBJIDX_INVALID;
} }
} }
@ -82,7 +93,7 @@ QSE_ASSERT (QSE_T("MEMORY ALLOCATION ERROR\n") == QSE_NULL);
stx->mem.free = (qse_stx_objptr_t*)*slot; stx->mem.free = (qse_stx_objptr_t*)*slot;
*slot = objptr; *slot = objptr;
QSE_MEMSET (objptr, 0, QSE_SIZEOF(nbytes)); QSE_MEMSET (objptr, 0, nbytes);
return (qse_stx_objidx_t)(slot - stx->mem.slot); return (qse_stx_objidx_t)(slot - stx->mem.slot);
} }
@ -98,3 +109,11 @@ void qse_stx_freemem (qse_stx_t* stx, qse_stx_objidx_t objidx)
stx->mem.free = &stx->mem.slot[objidx]; stx->mem.free = &stx->mem.slot[objidx];
} }
void qse_stx_swapmem (qse_stx_t* stx, qse_stx_objidx_t idx1, qse_stx_objidx_t idx2)
{
qse_stx_objptr_t tmp;
tmp = stx->mem.slot[idx1];
stx->mem.slot[idx1] = stx->mem.slot[idx2];
stx->mem.slot[idx2] = tmp;
}

View File

@ -32,6 +32,12 @@ void qse_stx_freemem (
qse_stx_objidx_t objidx qse_stx_objidx_t objidx
); );
void qse_stx_swapmem (
qse_stx_t* stx,
qse_stx_objidx_t idx1,
qse_stx_objidx_t idx2
);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -12,7 +12,7 @@ qse_word_t qse_stx_allocwordobj (
qse_size_t total_bytes; qse_size_t total_bytes;
qse_stx_objidx_t idx; qse_stx_objidx_t idx;
qse_word_t ref; qse_word_t ref;
qse_stx_wordobjptr_t ptr; qse_stx_wordobj_t* ptr;
total_nflds = nflds + variable_nflds; total_nflds = nflds + variable_nflds;
total_bytes = total_bytes =
@ -26,7 +26,7 @@ qse_word_t qse_stx_allocwordobj (
if (idx == QSE_STX_OBJIDX_INVALID) return stx->ref.nil; if (idx == QSE_STX_OBJIDX_INVALID) return stx->ref.nil;
ref = IDXTOREF(stx,idx); ref = IDXTOREF(stx,idx);
ptr = (qse_stx_wordobjptr_t)PTRBYIDX(stx,idx); ptr = (qse_stx_wordobj_t*)PTRBYIDX(stx,idx);
ptr->h._type = QSE_STX_WORDOBJ; ptr->h._type = QSE_STX_WORDOBJ;
ptr->h._mark = 0; ptr->h._mark = 0;
@ -71,19 +71,19 @@ qse_word_t qse_stx_allocbyteobj (
{ {
qse_stx_objidx_t idx; qse_stx_objidx_t idx;
qse_word_t ref; qse_word_t ref;
qse_stx_byteobjptr_t ptr; qse_stx_byteobj_t* ptr;
idx = qse_stx_allocmem ( idx = qse_stx_allocmem (
stx, variable_nflds + QSE_SIZEOF(qse_stx_objhdr_t)); stx, variable_nflds + QSE_SIZEOF(qse_stx_objhdr_t));
if (idx == QSE_STX_OBJIDX_INVALID) return stx->ref.nil; if (idx == QSE_STX_OBJIDX_INVALID) return stx->ref.nil;
ref = QSE_STX_IDXTOREF(stx,idx); ref = QSE_STX_IDXTOREF(stx,idx);
ptr = (qse_stx_byteobjptr_t)PTRBYIDX(stx,idx); ptr = (qse_stx_byteobj_t*)PTRBYIDX(stx,idx);
ptr->h._type = QSE_STX_BYTEOBJ; ptr->h._type = QSE_STX_BYTEOBJ;
ptr->h._mark = 0; ptr->h._mark = 0;
ptr->h._refcnt = 0; ptr->h._refcnt = 0;
ptr->h._size = variable_nflds; ptr->h._size = variable_nflds;
ptr->h._class = stx->ref.nil; ptr->h._class = stx->ref.nil;
ptr->h._backref = ref; ptr->h._backref = ref;
@ -114,7 +114,7 @@ qse_word_t qse_stx_alloccharobj (
{ {
qse_stx_objidx_t idx; qse_stx_objidx_t idx;
qse_word_t ref; qse_word_t ref;
qse_stx_charobjptr_t ptr; qse_stx_charobj_t* ptr;
qse_size_t total_bytes; qse_size_t total_bytes;
total_bytes = total_bytes =
@ -125,14 +125,17 @@ qse_word_t qse_stx_alloccharobj (
if (idx == QSE_STX_OBJIDX_INVALID) return stx->ref.nil; if (idx == QSE_STX_OBJIDX_INVALID) return stx->ref.nil;
ref = QSE_STX_IDXTOREF(stx,idx); ref = QSE_STX_IDXTOREF(stx,idx);
ptr = (qse_stx_charobjptr_t)PTRBYIDX(stx,idx); ptr = (qse_stx_charobj_t*)PTRBYIDX(stx,idx);
ptr->h._type = QSE_STX_CHAROBJ; ptr->h._type = QSE_STX_CHAROBJ;
ptr->h._mark = 0; ptr->h._mark = 0;
ptr->h._refcnt = 0; ptr->h._refcnt = 0;
ptr->h._size = variable_nflds; /* the size for the character object does not include
ptr->h._class = stx->ref.nil; * the extra 1 byte allocated for an implicit terminating
ptr->h._backref = ref; * '\0' character */
ptr->h._size = variable_nflds;
ptr->h._class = stx->ref.nil;
ptr->h._backref = ref;
if (variable_data) if (variable_data)
{ {
@ -189,118 +192,7 @@ qse_word_t qse_stx_allocn_char_object (qse_stx_t* stx, ...)
} }
#endif #endif
qse_word_t qse_stx_hashobj (qse_stx_t* stx, qse_word_t ref)
{
qse_word_t hv;
if (REFISINT(stx, ref))
{
qse_word_t tmp = REFTOINT(stx, ref);
hv = qse_stx_hashbytes (stx, &tmp, QSE_SIZEOF(tmp));
}
else
{
switch (OBJTYPE(stx,ref))
{
case BYTEOBJ:
hv = qse_stx_hashbytes (
stx,
&BYTEAT(stx,ref,0),
OBJSIZE(stx,ref)
);
break;
case CHAROBJ:
/* the additional null is not taken into account */
hv = qse_stx_hashbytes (
stx,
&CHARAT(stx,ref,0),
OBJSIZE(stx,ref) * QSE_SIZEOF(qse_char_t)
);
break;
case WORDOBJ:
hv = qse_stx_hashbytes (
stx,
&WORDAT(stx,ref,0),
OBJSIZE(stx,ref) * QSE_SIZEOF(qse_word_t)
);
break;
default:
QSE_ASSERT (
!"This should never happen"
);
break;
}
}
return hv;
}
#if 0 #if 0
qse_word_t qse_stx_instantiate (
qse_stx_t* stx, qse_stx_objref_t class, const void* data,
const void* variable_data, qse_word_t variable_nflds)
{
qse_stx_class_t* class_ptr;
qse_word_t spec, nflds, inst;
int indexable;
QSE_ASSERT (class != stx->class_smallinteger);
class_ptr = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class);
/* don't instantiate a metaclass whose instance must be
created in a different way */
/* TODO: maybe delete the following line */
QSE_ASSERT (QSE_STX_CLASS(class) != stx->class_metaclass);
QSE_ASSERT (QSE_STX_ISSMALLINT(class_obj->spec));
spec = QSE_STX_FROMSMALLINT(class_obj->spec);
nflds = (spec >> QSE_STX_SPEC_INDEXABLE_BITS);
indexable = spec & QSE_STX_SPEC_INDEXABLE_MASK;
switch (indexable)
{
case QSE_STX_SPEC_BYTE_INDEXABLE:
/* variable-size byte class */
QSE_ASSERT (nflds == 0 && data == QSE_NULL);
inst = qse_stx_alloc_byte_object(
stx, variable_data, variable_nflds);
break;
case QSE_STX_SPEC_CHAR_INDEXABLE:
/* variable-size char class */
QSE_ASSERT (nflds == 0 && data == QSE_NULL);
inst = qse_stx_alloc_char_objectx(
stx, variable_data, variable_nflds);
break;
case QSE_STX_SPEC_WORD_INDEXABLE:
/* variable-size class */
inst = qse_stx_alloc_word_object (
stx, data, nflds, variable_data, variable_nflds);
break;
case QSE_STX_SPEC_FIXED:
/* fixed size */
QSE_ASSERT (indexable == QSE_STX_SPEC_NOT_INDEXABLE);
QSE_ASSERT (variable_nflds == 0 && variable_data == QSE_NULL);
inst = qse_stx_alloc_word_object (
stx, data, nflds, QSE_NULL, 0);
break;
default:
/* this should never happen */
QSE_ASSERTX (0, "this should never happen");
inst = QSE_STX_OBJREF_INVALID;
}
if (inst != QSE_STX_OBJREF_INVALID)
QSE_STX_CLASSOF(stx,inst) = class;
return inst;
}
qse_word_t qse_stx_class (qse_stx_t* stx, qse_stx_objref_t obj) qse_word_t qse_stx_class (qse_stx_t* stx, qse_stx_objref_t obj)
{ {
return QSE_STX_ISSMALLINT(obj)? return QSE_STX_ISSMALLINT(obj)?

View File

@ -29,26 +29,7 @@ qse_word_t qse_stx_alloccharobj (
qse_word_t variable_nflds qse_word_t variable_nflds
); );
qse_word_t qse_stx_hashobj (
qse_stx_t* stx,
qse_word_t ref
);
#if 0 #if 0
qse_word_t qse_stx_alloc_word_object (
qse_stx_t* stx, const qse_word_t* data, qse_word_t nfields,
const qse_word_t* variable_data, qse_word_t variable_nfields);
qse_word_t qse_stx_alloc_byte_object (
qse_stx_t* stx, const qse_byte_t* data, qse_word_t n);
qse_word_t qse_stx_alloc_char_object (
qse_stx_t* stx, const qse_char_t* str);
qse_word_t qse_stx_alloc_char_objectx (
qse_stx_t* stx, const qse_char_t* str, qse_word_t n);
qse_word_t qse_stx_allocn_char_object (qse_stx_t* stx, ...);
qse_word_t qse_stx_instantiate ( qse_word_t qse_stx_instantiate (
qse_stx_t* stx, qse_word_t class_index, const void* data, qse_stx_t* stx, qse_word_t class_index, const void* data,
const void* variable_data, qse_word_t variable_nfields); const void* variable_data, qse_word_t variable_nfields);

View File

@ -12,17 +12,18 @@ typedef qse_word_t qse_stx_objidx_t;
typedef struct qse_stx_objhdr_t qse_stx_objhdr_t; /* object header */ typedef struct qse_stx_objhdr_t qse_stx_objhdr_t; /* object header */
typedef struct qse_stx_object_t qse_stx_object_t; /* abstract object */ typedef struct qse_stx_object_t qse_stx_object_t; /* abstract object */
typedef struct qse_stx_object_t* qse_stx_objptr_t; /* object pointer */ typedef struct qse_stx_object_t* qse_stx_objptr_t; /* object pointer */
typedef struct qse_stx_byteobj_t* qse_stx_byteobjptr_t;
typedef struct qse_stx_charobj_t* qse_stx_charobjptr_t; typedef struct qse_stx_byteobj_t qse_stx_byteobj_t;
typedef struct qse_stx_wordobj_t* qse_stx_wordobjptr_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 "hash.h"
#include "mem.h" #include "mem.h"
#include "obj.h" #include "obj.h"
#include "sym.h" #include "sym.h"
#include "dic.h" #include "dic.h"
#include "cls.h"
#include "boot.h" #include "boot.h"
enum qse_stx_objtype_t enum qse_stx_objtype_t
@ -105,13 +106,6 @@ struct qse_stx_t
qse_stx_objptr_t* free; qse_stx_objptr_t* free;
} mem; } mem;
struct
{
qse_size_t capa;
qse_size_t size;
qse_word_t* slot;
} symtab;
struct struct
{ {
qse_word_t nil; qse_word_t nil;
@ -132,7 +126,8 @@ struct qse_stx_t
qse_word_t class_string; qse_word_t class_string;
qse_word_t class_character; qse_word_t class_character;
qse_word_t class_context; qse_word_t class_context;
qse_word_t class_system_dictionary; qse_word_t class_systemsymboltable;
qse_word_t class_systemdictionary;
qse_word_t class_method; qse_word_t class_method;
qse_word_t class_smallinteger; qse_word_t class_smallinteger;
} ref; } ref;
@ -180,11 +175,11 @@ struct qse_stx_t
#define QSE_STX_OBJCLASS(stx,ref) (QSE_STX_PTRBYREF(stx,ref)->h._class) #define QSE_STX_OBJCLASS(stx,ref) (QSE_STX_PTRBYREF(stx,ref)->h._class)
#define QSE_STX_WORDAT(stx,ref,pos) \ #define QSE_STX_WORDAT(stx,ref,pos) \
(((qse_stx_wordobjptr_t)QSE_STX_PTRBYREF(stx,ref))->fld[pos]) (((qse_stx_wordobj_t*)QSE_STX_PTRBYREF(stx,ref))->fld[pos])
#define QSE_STX_BYTEAT(stx,ref,pos) \ #define QSE_STX_BYTEAT(stx,ref,pos) \
(((qse_stx_byteobjptr_t)QSE_STX_PTRBYREF(stx,ref))->fld[pos]) (((qse_stx_byteobj_t*)QSE_STX_PTRBYREF(stx,ref))->fld[pos])
#define QSE_STX_CHARAT(stx,ref,pos) \ #define QSE_STX_CHARAT(stx,ref,pos) \
(((qse_stx_charobjptr_t)QSE_STX_PTRBYREF(stx,ref))->fld[pos]) (((qse_stx_charobj_t*)QSE_STX_PTRBYREF(stx,ref))->fld[pos])
/* REDEFINITION DROPPING PREFIX FOR INTERNAL USE */ /* REDEFINITION DROPPING PREFIX FOR INTERNAL USE */
#define REFISINT(stx,x) QSE_STX_REFISINT(stx,x) #define REFISINT(stx,x) QSE_STX_REFISINT(stx,x)
@ -210,61 +205,14 @@ struct qse_stx_t
#define CHAROBJ QSE_STX_CHAROBJ #define CHAROBJ QSE_STX_CHAROBJ
#define WORDOBJ QSE_STX_WORDOBJ #define WORDOBJ QSE_STX_WORDOBJ
#if 0 /* SOME INTERNAL MACRO DEFINITIONS */
/* hardcoded object reference */ #define SYMTAB_INIT_CAPA 256
#define QSE_STX_NIL(stx) QSE_STX_IDXTOREF(stx,0) #define SYSDIC_INIT_CAPA 256
#define QSE_STX_TRUE(stx) QSE_STX_IDXTOREF(stx,1)
#define QSE_STX_FALSE(stx) QSE_STX_IDXTOREF(stx,2)
#define QSE_STX_DATA(stx,idx) ((void*)(QSE_STX_OBJPTR(stx,idx) + 1))
#endif
#if 0
#define QSE_STX_WORD_INDEXED (0x00)
#define QSE_STX_BYTE_INDEXED (0x01)
#define QSE_STX_CHAR_INDEXED (0x02)
/* this type has nothing to do with
* the indexability of the object... */
enum qse_stx_objtype_t
{
QSE_STX_OBJTYPE_BYTE,
QSE_STX_OBJTYPE_CHAR,
QSE_STX_OBJTYPE_WORD
};
#define QSE_STX_ISWORDOBJECT(stx,idx) \
(QSE_STX_TYPE(stx,idx) == QSE_STX_WORD_INDEXED)
#define QSE_STX_ISBYTEOBJECT(stx,idx) \
(QSE_STX_TYPE(stx,idx) == QSE_STX_BYTE_INDEXED)
#define QSE_STX_ISCHAROBJECT(stx,idx) \
(QSE_STX_TYPE(stx,idx) == QSE_STX_CHAR_INDEXED)
#define QSE_STX_WORDOBJPTR(stx,idx) \
((qse_stx_word_object_t*)QSE_STX_OBJPTR(stx,idx))
#define QSE_STX_BYTEOBJPTR(stx,idx) \
((qse_stx_byte_object_t*)QSE_STX_OBJPTR(stx,idx))
#define QSE_STX_CHAROBJPTR(stx,idx) \
((qse_stx_char_object_t*)QSE_STX_OBJPTR(stx,idx))
#define QSE_STX_WORD_AT(stx,idx,n) \
(QSE_STX_WORD_OBJECT(stx,idx)->data[n])
#define QSE_STX_BYTE_AT(stx,idx,n) \
(QSE_STX_BYTE_OBJECT(stx,idx)->data[n])
#define QSE_STX_CHAR_AT(stx,idx,n) \
(QSE_STX_CHAR_OBJECT(stx,idx)->data[n])
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*
*
*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -16,25 +16,95 @@ struct qse_stx_symtab_t
typedef struct qse_stx_symtab_t qse_stx_symtab_t; typedef struct qse_stx_symtab_t qse_stx_symtab_t;
qse_word_t qse_stx_newsymbol ( static qse_word_t expand (qse_stx_t* stx, qse_word_t tabref)
{
qse_word_t oldcapa, newcapa;
qse_word_t newtab;
qse_stx_symtab_t* oldptr, * newptr;
QSE_ASSERTX (
REFISIDX(stx,tabref),
"The reference is not an object index"
);
/* This function can handle expansion of an object whose class is
* SystemSymbolTable. During initial bootstrapping, the class of
* the stock symbol table (stx->ref.symtab) may not be set properly.
* You must make sure that expansion is not triggered until its class
* is set. If this assertion fails, you must increase the value of
* SYMTAB_INIT_CAPA.
*/
QSE_ASSERT (OBJCLASS(stx,tabref) == stx->ref.class_systemsymboltable);
/* get the current table capacity being the size of the object
* excluding the tally field. */
oldcapa = OBJSIZE(stx,tabref) - 1;
/* 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
);
if (newtab == stx->ref.nil) return stx->ref.nil;
oldptr = (qse_stx_symtab_t*)PTRBYREF(stx,tabref);
newptr = (qse_stx_symtab_t*)PTRBYREF(stx,newtab);
newptr->tally = INTTOREF (stx, 0);
while (oldcapa > 0)
{
qse_word_t symbol;
symbol = oldptr->slot[--oldcapa];
if (symbol != stx->ref.nil)
{
qse_word_t index;
QSE_ASSERT (REFISIDX(stx,symbol));
QSE_ASSERT (OBJCLASS(stx,symbol) == stx->ref.class_symbol);
QSE_ASSERT (OBJTYPE(stx,symbol) == CHAROBJ);
/* qse_stx_newsymbol uses qse_stx_hashstr().
* this function uses qse_stx_hashobj().
* both must return the same value */
QSE_ASSERT (qse_stx_hashobj (stx, symbol) ==
qse_stx_hashstr (stx, &CHARAT(stx,symbol,0)));
index = qse_stx_hashobj (stx, symbol) % newcapa;
while (newptr->slot[index] != stx->ref.nil)
index = (index + 1) % newcapa;
newptr->slot[index] = symbol;
}
}
qse_stx_swapmem (stx, REFTOIDX(stx,tabref), REFTOIDX(stx,newtab));
newptr->tally = oldptr->tally;
return tabref;
}
static qse_word_t new_symbol (
qse_stx_t* stx, qse_word_t tabref, const qse_char_t* name) qse_stx_t* stx, qse_word_t tabref, const qse_char_t* name)
{ {
qse_stx_symtab_t* tabptr; qse_stx_symtab_t* tabptr;
qse_word_t symref; qse_word_t symref;
qse_word_t capa, hash, tally; qse_word_t capa, hash, index, tally;
/* 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);
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);
index = hash % capa;
tabptr = (qse_stx_symtab_t*)PTRBYREF(stx,tabref); tabptr = (qse_stx_symtab_t*)PTRBYREF(stx,tabref);
tally = REFTOINT(stx, tabptr->tally);
do do
{ {
symref = tabptr->slot[hash]; /*symref = WORDAT (stx, tabref, index + 1);*/
symref = tabptr->slot[index];
if (symref == stx->ref.nil) break; /* not found */ if (symref == stx->ref.nil) break; /* not found */
QSE_ASSERT (REFISIDX(stx,symref)); QSE_ASSERT (REFISIDX(stx,symref));
@ -46,20 +116,31 @@ qse_word_t qse_stx_newsymbol (
name) == 0) return symref;*/ name) == 0) return symref;*/
if (qse_strcmp (&CHARAT(stx,symref,0), name) == 0) return symref; if (qse_strcmp (&CHARAT(stx,symref,0), name) == 0) return symref;
hash = (hash + 1) % capa; index = (index + 1) % capa;
} }
while (0); while (0);
/* symbol is not found. let's create a new symbol */
tally = REFTOINT(stx, tabptr->tally);
/* check if the symbol table is getting full soon */
if (tally + 1 >= capa) if (tally + 1 >= capa)
{ {
/* Enlarge the symbol table before it gets full to make sure that /* Enlarge the symbol table before it gets full to
* it has at least one free slot. */ * 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 0 /* refresh the object pointer */
if (grow (stx, tab) <= -1) return -1; tabptr = (qse_stx_symtab_t*)PTRBYREF(stx,tabref);
/* refresh tally */
tally = REFTOINT (stx, tabptr->tally); /* refersh capacity and hash index */
#endif capa = OBJSIZE(stx,tabref) - 1; /* exclude the tally field */
index = hash % capa;
/* after expansion, the tally must still be the same */
QSE_ASSERT (tally == REFTOINT (stx, tabptr->tally));
} }
symref = qse_stx_alloccharobj (stx, name, qse_strlen(name)); symref = qse_stx_alloccharobj (stx, name, qse_strlen(name));
@ -67,105 +148,18 @@ qse_word_t qse_stx_newsymbol (
{ {
OBJCLASS(stx,symref) = stx->ref.class_symbol; OBJCLASS(stx,symref) = stx->ref.class_symbol;
tabptr->tally = INTTOREF (stx, tally + 1); tabptr->tally = INTTOREF (stx, tally + 1);
tabptr->slot[hash] = symref; tabptr->slot[index] = symref;
} }
return symref; return symref;
} }
qse_word_t qse_stx_newsymbol (qse_stx_t* stx, const qse_char_t* name)
{
return new_symbol (stx, stx->ref.symtab, name);
}
#if 0 #if 0
#include "stx.h"
static int __grow_symtab (qse_stx_t* stx)
{
qse_word_t capa, ncapa, i, j;
qse_word_t* nspace;
capa = stx->symtab.capa;
ncapa = capa << 1; /* double the capacity */
/* TODO: allocate symbol table from stx->mem......... */
nspace = (qse_word_t*) QSE_MMGR_ALLOC (
stx->mmgr, ncapa * QSE_SIZEOF(*nspace)
);
if (nspace == QSE_NULL)
{
/* TODO: handle memory error */
qse_stx_seterrnum (stx, QSE_STX_ENOMEM);
return -1;
}
for (i = 0; i < capa; i++)
{
qse_word_t x = stx->symtab.slot[i];
if (x == stx->nil) continue;
j = qse_stx_strxhash (
QSE_STX_DATA(stx,x), QSE_STX_SIZE(stx,x)) % ncapa;
while (1)
{
if (nspace[j] == stx->nil)
{
nspace[j] = x;
break;
}
j = (j % ncapa) + 1;
}
}
stx->symtab.capa = ncapa;
QSE_MMGR_FREE (stx->mmgr, stx->symtab.slot);
stx->symtab.slot = nspace;
return 0;
}
qse_word_t qse_stx_newsym (qse_stx_t* stx, const qse_char_t* name)
{
return qse_stx_newsymwithlen (stx, name, qse_strlen(name));
}
qse_word_t qse_stx_newsymwithlen (qse_stx_t* stx, const qse_char_t* name, qse_word_t len)
{
qse_word_t capa, hash, index, size, x;
capa = stx->symtab.capa;
size = stx->symtab.size;
if (capa <= size + 1)
{
if (__grow_symtab (stx) <= -1)
{
/* TODO: .... */
}
capa = stx->symtab.capa;
}
hash = qse_stx_strxhash(name,len);
index = hash % stx->symtab.capa;
while (1)
{
x = stx->symtab.slot[index];
if (x == stx->nil)
{
/* insert a new item into an empty slot */
x = qse_stx_alloc_char_objectx (stx, name, len);
QSE_STX_CLASS(stx,x) = stx->class_symbol;
stx->symtab.slot[index] = x;
stx->symtab.size++;
break;
}
if (qse_strxncmp (name, len, QSE_STX_DATA(stx,x), QSE_STX_SIZE(stx,x)) == 0) break;
index = (index % stx->symtab.capa) + 1;
}
return x;
}
void qse_stx_traverse_symbol_table ( void qse_stx_traverse_symbol_table (
qse_stx_t* stx, void (*func) (qse_stx_t*,qse_word_t,void*), void* data) qse_stx_t* stx, void (*func) (qse_stx_t*,qse_word_t,void*), void* data)
{ {

View File

@ -5,7 +5,7 @@
#ifndef _QSE_LIB_STX_SYM_H_ #ifndef _QSE_LIB_STX_SYM_H_
#define _QSE_LIB_STX_SYM_H_ #define _QSE_LIB_STX_SYM_H_
/* The SystemSymbolTable is a word variable class. /* The SystemSymbolTable is a variable word class.
* The info below is for the fixed part only */ * The info below is for the fixed part only */
#define QSE_STX_SYMTAB_SIZE 1 #define QSE_STX_SYMTAB_SIZE 1
#define QSE_STX_SYMTAB_TALLY 0 #define QSE_STX_SYMTAB_TALLY 0
@ -16,7 +16,6 @@ extern "C" {
qse_word_t qse_stx_newsymbol ( qse_word_t qse_stx_newsymbol (
qse_stx_t* stx, qse_stx_t* stx,
qse_word_t tabref,
const qse_char_t* name const qse_char_t* name
); );