added more code for symbol table, system dictionary, bootstrapping
This commit is contained in:
parent
3cc4595018
commit
fb46d98bb2
@ -8,6 +8,6 @@ AM_CPPFLAGS = \
|
||||
|
||||
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_LIBADD = -lqsecmn
|
||||
|
@ -72,7 +72,7 @@ am__installdirs = "$(DESTDIR)$(libdir)"
|
||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||
libqsestx_la_DEPENDENCIES =
|
||||
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_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
@ -239,7 +239,7 @@ AM_CPPFLAGS = \
|
||||
-I$(includedir)
|
||||
|
||||
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_LIBADD = -lqsecmn
|
||||
all: all-am
|
||||
@ -317,6 +317,7 @@ distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@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)/err.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@
|
||||
|
@ -3,11 +3,9 @@
|
||||
*/
|
||||
|
||||
#include "stx.h"
|
||||
#include "mem.h"
|
||||
#include "sym.h"
|
||||
#include "class.h"
|
||||
#include <qse/cmn/str.h>
|
||||
|
||||
static void make_intrinsic_classes (qse_stx_t* stx);
|
||||
static int make_intrinsic_classes (qse_stx_t* stx);
|
||||
#if 0
|
||||
static qse_word_t __make_classvar_dict (
|
||||
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);
|
||||
static void __set_metaclass_subclasses (
|
||||
qse_stx_t* stx, qse_word_t* array, const qse_char_t* str);
|
||||
#endif
|
||||
|
||||
struct class_info_t
|
||||
{
|
||||
@ -213,6 +212,14 @@ static class_info_t class_info[] =
|
||||
QSE_NULL,
|
||||
SPEC_VARIABLE_BYTE
|
||||
},
|
||||
{
|
||||
QSE_T("SystemSymbolTable"),
|
||||
QSE_T("IndexedCollection"),
|
||||
QSE_T("tally"),
|
||||
QSE_NULL,
|
||||
QSE_NULL,
|
||||
SPEC_VARIABLE_WORD
|
||||
},
|
||||
{
|
||||
QSE_T("Dictionary"),
|
||||
QSE_T("IndexedCollection"),
|
||||
@ -221,6 +228,7 @@ static class_info_t class_info[] =
|
||||
QSE_NULL,
|
||||
SPEC_VARIABLE_WORD
|
||||
},
|
||||
|
||||
{
|
||||
QSE_T("SystemDictionary"),
|
||||
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_ASSERT (stx->class_string != stx->nil);
|
||||
x = qse_stx_alloc_char_object (stx, str);
|
||||
QSE_STX_CLASS(stx,x) = stx->class_string;
|
||||
QSE_ASSERT (REFISIDX(stx,stx->ref.class_string));
|
||||
QSE_ASSERT (stx->ref.class_string != stx->ref.nil);
|
||||
|
||||
x = qse_stx_alloccharobj (stx, str, qse_strlen(str));
|
||||
if (x != stx->ref.nil) OBJCLASS(stx,x) = stx->ref.class_string;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
static void make_intrinsic_classes (qse_stx_t* stx)
|
||||
static int make_intrinsic_classes (qse_stx_t* stx)
|
||||
{
|
||||
class_info_t* p;
|
||||
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_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++)
|
||||
{
|
||||
class = qse_stx_lookup_class(stx, p->name);
|
||||
if (class == stx->nil)
|
||||
class = qse_stx_findclass(stx, p->name);
|
||||
if (class == stx->ref.nil)
|
||||
{
|
||||
class = qse_stx_newclass (stx, p->name);
|
||||
if (class == stx->ref.nil) return stx->ref.nil;
|
||||
}
|
||||
|
||||
QSE_ASSERT (class != stx->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);
|
||||
QSE_ASSERT (class != stx->ref.nil);
|
||||
|
||||
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;
|
||||
if (p->superclass != QSE_NULL) {
|
||||
if (p->superclass)
|
||||
{
|
||||
qse_word_t meta;
|
||||
qse_stx_metaclass_t* meta_obj;
|
||||
|
||||
superclass = qse_stx_lookup_class(stx,p->superclass);
|
||||
QSE_ASSERT (superclass != stx->nil);
|
||||
superclass = qse_stx_findclass (stx, p->superclass);
|
||||
QSE_ASSERT (superclass != stx->ref.nil);
|
||||
|
||||
meta = class_obj->header.class;
|
||||
meta_obj = (qse_stx_metaclass_t*)QSE_STX_OBJPTR(stx,meta);
|
||||
meta_obj->superclass = QSE_STX_CLASS(stx,superclass);
|
||||
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;
|
||||
|
||||
while (superclass != stx->nil) {
|
||||
while (superclass != stx->ref.nil)
|
||||
{
|
||||
superclass_obj = (qse_stx_class_t*)
|
||||
QSE_STX_OBJPTR(stx,superclass);
|
||||
nfields +=
|
||||
@ -327,13 +344,14 @@ static void make_intrinsic_classes (qse_stx_t* stx)
|
||||
QSE_STX_SPEC_INDEXABLE_BITS;
|
||||
superclass = superclass_obj->superclass;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (p->instance_variables != QSE_NULL) {
|
||||
if (p->instance_variables)
|
||||
{
|
||||
nfields += __count_names (p->instance_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 &&
|
||||
@ -346,7 +364,7 @@ static void make_intrinsic_classes (qse_stx_t* stx)
|
||||
for (p = class_info; p->name != QSE_NULL; p++)
|
||||
{
|
||||
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);
|
||||
|
||||
@ -373,7 +391,7 @@ static void make_intrinsic_classes (qse_stx_t* stx)
|
||||
__set_subclasses (stx, QSE_STX_DATA(stx,array), 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->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);
|
||||
|
||||
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_obj = (qse_stx_metaclass_t*)QSE_STX_OBJPTR(stx, metaclass);
|
||||
metaclass_obj->subclasses = array;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 (qse_strcmp (str, p->superclass) != 0) continue;
|
||||
class = qse_stx_lookup_class (stx, p->name);
|
||||
QSE_ASSERT (class != stx->nil);
|
||||
QSE_ASSERT (class != stx->ref.nil);
|
||||
array[n++] = class;
|
||||
}
|
||||
}
|
||||
@ -471,7 +491,7 @@ static void __set_metaclass_subclasses (
|
||||
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->nil);
|
||||
QSE_ASSERT (class != stx->ref.nil);
|
||||
array[n++] = QSE_STX_CLASS(stx,class);
|
||||
}
|
||||
}
|
||||
@ -484,7 +504,7 @@ static qse_word_t __make_classvar_dict (
|
||||
const qse_char_t* name;
|
||||
|
||||
dict = qse_stx_instantiate (
|
||||
stx, stx->class_system_dictionary,
|
||||
stx, stx->class_systemdictionary,
|
||||
QSE_NULL, QSE_NULL, __count_names(names));
|
||||
|
||||
do {
|
||||
@ -498,7 +518,7 @@ static qse_word_t __make_classvar_dict (
|
||||
*p != QSE_T('\0')) p++;
|
||||
|
||||
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);
|
||||
|
||||
return dict;
|
||||
@ -518,7 +538,7 @@ static int sketch_nil (qse_stx_t* stx)
|
||||
{
|
||||
qse_stx_objidx_t idx;
|
||||
qse_word_t ref;
|
||||
qse_stx_wordobjptr_t ptr;
|
||||
qse_stx_wordobj_t* ptr;
|
||||
|
||||
/* nil contains no member fields. allocate space for
|
||||
* an object header */
|
||||
@ -526,7 +546,7 @@ static int sketch_nil (qse_stx_t* stx)
|
||||
if (idx == QSE_STX_OBJIDX_INVALID) return -1;
|
||||
|
||||
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 */
|
||||
stx->ref.nil = ref;
|
||||
@ -548,14 +568,28 @@ static int sketch_nil (qse_stx_t* stx)
|
||||
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)
|
||||
{
|
||||
qse_word_t class_SymbolMeta;
|
||||
qse_word_t class_MetaclassMeta;
|
||||
qse_word_t class_AssociationMeta;
|
||||
qse_word_t symbol_Symbol;
|
||||
qse_word_t symbol_Metaclass;
|
||||
qse_word_t symbol_Association;
|
||||
qse_word_t symbol_symbol;
|
||||
qse_word_t symbol_metaclass;
|
||||
qse_word_t symbol_association;
|
||||
|
||||
/* allocate true and false. the class pointer is not correct yet */
|
||||
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 */
|
||||
/* 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. */
|
||||
WORDAT(stx,stx->ref.symtab,QSE_STX_SYMTAB_TALLY) = INTTOREF(stx,0);
|
||||
|
||||
/* global system dictionary */
|
||||
/* 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 */
|
||||
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 */
|
||||
|
||||
/* #Symbol */
|
||||
symbol_Symbol = qse_stx_newsymbol (
|
||||
stx, stx->ref.symtab, QSE_T("Symbol"));
|
||||
NEW_SYMBOL_TO (stx, symbol_symbol, QSE_T("Symbol"));
|
||||
/* #Metaclass */
|
||||
symbol_Metaclass = qse_stx_newsymbol (
|
||||
stx, stx->ref.symtab, QSE_T("Metaclass"));
|
||||
NEW_SYMBOL_TO (stx, symbol_metaclass, QSE_T("Metaclass"));
|
||||
/* #Association */
|
||||
symbol_Association = qse_stx_newsymbol (
|
||||
stx, stx->ref.symtab, QSE_T("Association"));
|
||||
NEW_SYMBOL_TO (stx, symbol_association, QSE_T("Association"));
|
||||
|
||||
/* 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 */
|
||||
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 */
|
||||
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 */
|
||||
qse_stx_dict_put (stx,
|
||||
stx->ref.sysdic, symbol_Symbol, stx->class_symbol);
|
||||
qse_stx_dict_put (stx,
|
||||
stx->ref.sysdic, symbol_Metaclass, stx->class_metaclass);
|
||||
qse_stx_dict_put (stx,
|
||||
stx->ref.sysdic, symbol_Association, stx->class_association);
|
||||
#endif
|
||||
ADD_TO_SYSDIC (stx, symbol_symbol, stx->ref.class_symbol);
|
||||
ADD_TO_SYSDIC (stx, symbol_metaclass, stx->ref.class_metaclass);
|
||||
ADD_TO_SYSDIC (stx, symbol_association, stx->ref.class_association);
|
||||
|
||||
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)
|
||||
{
|
||||
qse_word_t symbol_Smalltalk;
|
||||
qse_word_t symbol_smalltalk;
|
||||
qse_word_t object_meta;
|
||||
|
||||
/* 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 */
|
||||
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;
|
||||
|
||||
#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_meta = QSE_STX_CLASS(stx,stx->class_object);
|
||||
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 */
|
||||
QSE_STX_CLASS(stx,stx->sysdic) = stx->class_system_dictionary;
|
||||
|
||||
symbol_Smalltalk = qse_stx_new_symbol (stx, QSE_T("Smalltalk"));
|
||||
qse_stx_dict_put (stx, stx->sysdic, symbol_Smalltalk, stx->sysdic);
|
||||
OBJCLASS(stx,stx->ref.sysdic) = stx->class_systemdictionary;
|
||||
NEW_SYMBOL_TO (stx, symbol_smalltalk, QSE_T("Smalltalk"));
|
||||
ADD_TO_SYSDIC (stx, symbol_smalltalk, stx->ref.sysdic);
|
||||
|
||||
/* create #nil, #true, #false */
|
||||
qse_stx_new_symbol (stx, QSE_T("nil"));
|
||||
qse_stx_new_symbol (stx, QSE_T("true"));
|
||||
qse_stx_new_symbol (stx, QSE_T("false"));
|
||||
NEW_SYMBOL_TO (stx, symbol_nil, QSE_T("nil"));
|
||||
NEW_SYMBOL_TO (stx, symbol_true, QSE_T("true"));
|
||||
NEW_SYMBOL_TO (stx, symbol_false, QSE_T("false"));
|
||||
|
||||
/* nil setClass: UndefinedObject */
|
||||
QSE_STX_CLASS(stx,stx->nil) =
|
||||
qse_stx_lookup_class(stx, QSE_T("UndefinedObject"));
|
||||
OBJCLASS(stx,stx->ref.nil) = qse_stx_findclass (stx, QSE_T("UndefinedObject"));
|
||||
/* true setClass: True */
|
||||
QSE_STX_CLASS(stx,stx->true) =
|
||||
qse_stx_lookup_class (stx, QSE_T("True"));
|
||||
OBJCLASS(stx,stx->ref.true) = qse_stx_findclass (stx, QSE_T("True"));
|
||||
/* fales setClass: False */
|
||||
QSE_STX_CLASS(stx,stx->false) =
|
||||
qse_stx_lookup_class (stx, QSE_T("False"));
|
||||
OBJCLASS(stx,stx->ref.false) = qse_stx_findclass (stx, QSE_T("False"));
|
||||
|
||||
__filein_kernel (stx);
|
||||
return 0;
|
||||
|
@ -32,11 +32,11 @@ qse_word_t qse_stx_newclass (qse_stx_t* stx, const qse_char_t* name)
|
||||
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;
|
||||
|
||||
assoc = qse_stx_dict_lookup (stx, stx->smalltalk, name);
|
||||
assoc = qse_stx_dict_lookup (stx, stx->ref.sysdic, name);
|
||||
if (assoc == 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);
|
||||
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;
|
||||
}
|
||||
@ -167,3 +167,67 @@ qse_word_t qse_stx_lookup_method (qse_stx_t* stx,
|
||||
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;
|
||||
}
|
||||
|
@ -66,9 +66,15 @@ typedef struct qse_stx_metaclass_t qse_stx_metaclass_t;
|
||||
extern "C" {
|
||||
#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 (
|
||||
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 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
|
||||
}
|
||||
#endif
|
||||
|
272
qse/lib/stx/cls.c
Normal file
272
qse/lib/stx/cls.c
Normal 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
75
qse/lib/stx/cls.h
Normal 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
|
@ -44,45 +44,40 @@ static qse_word_t new_assoc (
|
||||
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:
|
||||
* 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_system_dictionary != stx->ref.nil);
|
||||
QSE_ASSERT (stx->ref.class_systemdictionary != stx->ref.nil);
|
||||
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);
|
||||
new = qse_stx_instantiate (stx,
|
||||
newref = qse_stx_instantiate (stx,
|
||||
OBJCLASS(stx,dic), QSE_NULL, QSE_NULL, (size - 1) * 2);
|
||||
if (new == stx->ref.nil) return stx->ref.nil;
|
||||
WORDAT(stx,new,QSE_STX_DIC_TALLY) = INTTOREF (stx, 0);
|
||||
if (newref == stx->ref.nil) return stx->ref.nil;
|
||||
WORDAT(stx,newref,QSE_STX_DIC_TALLY) = INTTOREF (stx, 0);
|
||||
|
||||
for (index = 1; index < size; index++)
|
||||
{
|
||||
assoc = WORDAT(stx,dic,index);
|
||||
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_VALUE));
|
||||
WORDAT(stx,assoc,QSE_STX_ASSOC_VALUE)) == stx->ref.nil)
|
||||
{
|
||||
return stx->ref.nil;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: explore if dic can be immediately destroyed. */
|
||||
|
||||
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
|
||||
);
|
||||
qse_stx_swapmem (stx, REFTOIDX(stx,dic), REFTOIDX(stx,newref));
|
||||
|
||||
return dic;
|
||||
}
|
||||
@ -97,7 +92,7 @@ static qse_word_t find_slot (
|
||||
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);
|
||||
OBJCLASS(stx,key) == stx->ref.class_systemdictionary);
|
||||
|
||||
/* ensure that the key is a symbol */
|
||||
QSE_ASSERT (REFISIDX(stx,key));
|
||||
@ -145,7 +140,7 @@ qse_word_t qse_stx_lookupdic (
|
||||
QSE_ASSERT (REFISIDX(stx,dic));
|
||||
QSE_ASSERT (OBJTYPE(stx,dic) == WORDOBJ);
|
||||
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 */
|
||||
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.
|
||||
* - 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 */
|
||||
tally = REFTOINT(stx,WORDAT(stx,dic,QSE_STX_DIC_TALLY));
|
||||
|
@ -9,7 +9,7 @@
|
||||
#define QSE_STX_ASSOC_KEY 0
|
||||
#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 */
|
||||
#define QSE_STX_DIC_SIZE 1
|
||||
#define QSE_STX_DIC_TALLY 0
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "stx.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_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));
|
||||
}
|
||||
|
||||
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
|
||||
qse_char_t* qse_stx_strword (
|
||||
|
@ -26,6 +26,13 @@ qse_word_t qse_stx_hashstrx (
|
||||
qse_word_t len
|
||||
);
|
||||
|
||||
qse_word_t qse_stx_hashobj (
|
||||
qse_stx_t* stx,
|
||||
qse_word_t ref
|
||||
);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -20,7 +20,11 @@ int qse_stx_initmem (qse_stx_t* stx, qse_size_t capa)
|
||||
stx->mmgr,
|
||||
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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
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
|
||||
@ -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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -82,7 +93,7 @@ QSE_ASSERT (QSE_T("MEMORY ALLOCATION ERROR\n") == QSE_NULL);
|
||||
stx->mem.free = (qse_stx_objptr_t*)*slot;
|
||||
*slot = objptr;
|
||||
|
||||
QSE_MEMSET (objptr, 0, QSE_SIZEOF(nbytes));
|
||||
QSE_MEMSET (objptr, 0, nbytes);
|
||||
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];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -32,6 +32,12 @@ void qse_stx_freemem (
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
@ -12,7 +12,7 @@ qse_word_t qse_stx_allocwordobj (
|
||||
qse_size_t total_bytes;
|
||||
qse_stx_objidx_t idx;
|
||||
qse_word_t ref;
|
||||
qse_stx_wordobjptr_t ptr;
|
||||
qse_stx_wordobj_t* ptr;
|
||||
|
||||
total_nflds = nflds + variable_nflds;
|
||||
total_bytes =
|
||||
@ -26,7 +26,7 @@ qse_word_t qse_stx_allocwordobj (
|
||||
if (idx == QSE_STX_OBJIDX_INVALID) return stx->ref.nil;
|
||||
|
||||
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._mark = 0;
|
||||
@ -71,14 +71,14 @@ qse_word_t qse_stx_allocbyteobj (
|
||||
{
|
||||
qse_stx_objidx_t idx;
|
||||
qse_word_t ref;
|
||||
qse_stx_byteobjptr_t ptr;
|
||||
qse_stx_byteobj_t* ptr;
|
||||
|
||||
idx = qse_stx_allocmem (
|
||||
stx, variable_nflds + QSE_SIZEOF(qse_stx_objhdr_t));
|
||||
if (idx == QSE_STX_OBJIDX_INVALID) return stx->ref.nil;
|
||||
|
||||
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._mark = 0;
|
||||
@ -114,7 +114,7 @@ qse_word_t qse_stx_alloccharobj (
|
||||
{
|
||||
qse_stx_objidx_t idx;
|
||||
qse_word_t ref;
|
||||
qse_stx_charobjptr_t ptr;
|
||||
qse_stx_charobj_t* ptr;
|
||||
qse_size_t total_bytes;
|
||||
|
||||
total_bytes =
|
||||
@ -125,11 +125,14 @@ qse_word_t qse_stx_alloccharobj (
|
||||
if (idx == QSE_STX_OBJIDX_INVALID) return stx->ref.nil;
|
||||
|
||||
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._mark = 0;
|
||||
ptr->h._refcnt = 0;
|
||||
/* the size for the character object does not include
|
||||
* the extra 1 byte allocated for an implicit terminating
|
||||
* '\0' character */
|
||||
ptr->h._size = variable_nflds;
|
||||
ptr->h._class = stx->ref.nil;
|
||||
ptr->h._backref = ref;
|
||||
@ -189,118 +192,7 @@ qse_word_t qse_stx_allocn_char_object (qse_stx_t* stx, ...)
|
||||
}
|
||||
#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
|
||||
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)
|
||||
{
|
||||
return QSE_STX_ISSMALLINT(obj)?
|
||||
|
@ -29,26 +29,7 @@ qse_word_t qse_stx_alloccharobj (
|
||||
qse_word_t variable_nflds
|
||||
);
|
||||
|
||||
qse_word_t qse_stx_hashobj (
|
||||
qse_stx_t* stx,
|
||||
qse_word_t ref
|
||||
);
|
||||
|
||||
|
||||
#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_stx_t* stx, qse_word_t class_index, const void* data,
|
||||
const void* variable_data, qse_word_t variable_nfields);
|
||||
|
@ -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_object_t qse_stx_object_t; /* abstract object */
|
||||
|
||||
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_wordobj_t* qse_stx_wordobjptr_t;
|
||||
|
||||
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
|
||||
@ -105,13 +106,6 @@ struct qse_stx_t
|
||||
qse_stx_objptr_t* free;
|
||||
} mem;
|
||||
|
||||
struct
|
||||
{
|
||||
qse_size_t capa;
|
||||
qse_size_t size;
|
||||
qse_word_t* slot;
|
||||
} symtab;
|
||||
|
||||
struct
|
||||
{
|
||||
qse_word_t nil;
|
||||
@ -132,7 +126,8 @@ struct qse_stx_t
|
||||
qse_word_t class_string;
|
||||
qse_word_t class_character;
|
||||
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_smallinteger;
|
||||
} 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_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) \
|
||||
(((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) \
|
||||
(((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 */
|
||||
#define REFISINT(stx,x) QSE_STX_REFISINT(stx,x)
|
||||
@ -210,61 +205,14 @@ struct qse_stx_t
|
||||
#define CHAROBJ QSE_STX_CHAROBJ
|
||||
#define WORDOBJ QSE_STX_WORDOBJ
|
||||
|
||||
#if 0
|
||||
/* hardcoded object reference */
|
||||
#define QSE_STX_NIL(stx) QSE_STX_IDXTOREF(stx,0)
|
||||
#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
|
||||
/* SOME INTERNAL MACRO DEFINITIONS */
|
||||
#define SYMTAB_INIT_CAPA 256
|
||||
#define SYSDIC_INIT_CAPA 256
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -16,25 +16,95 @@ struct 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_symtab_t* tabptr;
|
||||
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 */
|
||||
QSE_ASSERT (OBJSIZE(stx,tabref) > 1);
|
||||
|
||||
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);
|
||||
tally = REFTOINT(stx, tabptr->tally);
|
||||
|
||||
do
|
||||
{
|
||||
symref = tabptr->slot[hash];
|
||||
/*symref = WORDAT (stx, tabref, index + 1);*/
|
||||
symref = tabptr->slot[index];
|
||||
if (symref == stx->ref.nil) break; /* not found */
|
||||
|
||||
QSE_ASSERT (REFISIDX(stx,symref));
|
||||
@ -46,20 +116,31 @@ qse_word_t qse_stx_newsymbol (
|
||||
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);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* Enlarge the symbol table before it gets full to make sure that
|
||||
* it has at least one free slot. */
|
||||
/* Enlarge the symbol table before it gets full to
|
||||
* 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
|
||||
if (grow (stx, tab) <= -1) return -1;
|
||||
/* refresh tally */
|
||||
tally = REFTOINT (stx, tabptr->tally);
|
||||
#endif
|
||||
/* refresh the object pointer */
|
||||
tabptr = (qse_stx_symtab_t*)PTRBYREF(stx,tabref);
|
||||
|
||||
/* refersh capacity and hash index */
|
||||
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));
|
||||
@ -67,105 +148,18 @@ qse_word_t qse_stx_newsymbol (
|
||||
{
|
||||
OBJCLASS(stx,symref) = stx->ref.class_symbol;
|
||||
tabptr->tally = INTTOREF (stx, tally + 1);
|
||||
tabptr->slot[hash] = symref;
|
||||
tabptr->slot[index] = 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
|
||||
#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 (
|
||||
qse_stx_t* stx, void (*func) (qse_stx_t*,qse_word_t,void*), void* data)
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
#ifndef _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 */
|
||||
#define QSE_STX_SYMTAB_SIZE 1
|
||||
#define QSE_STX_SYMTAB_TALLY 0
|
||||
@ -16,7 +16,6 @@ extern "C" {
|
||||
|
||||
qse_word_t qse_stx_newsymbol (
|
||||
qse_stx_t* stx,
|
||||
qse_word_t tabref,
|
||||
const qse_char_t* name
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user