revised bootstrapping code
This commit is contained in:
parent
c7b3ece237
commit
682cfc1949
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* $Id: array.c 118 2008-03-03 11:21:33Z baconevi $
|
||||
*/
|
||||
|
||||
#include <qse/stx/array.h>
|
||||
#include <qse/stx/object.h>
|
||||
#include <qse/bas/assert.h>
|
||||
|
||||
qse_word_t qse_stx_new_array (qse_stx_t* stx, qse_word_t size)
|
||||
{
|
||||
qse_word_t x;
|
||||
|
||||
qse_assert (stx->class_array != stx->nil);
|
||||
x = qse_stx_alloc_word_object (stx, QSE_NULL, 0, QSE_NULL, size);
|
||||
QSE_STX_CLASS(stx,x) = stx->class_array;
|
||||
|
||||
return x;
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* $Id: array.h 118 2008-03-03 11:21:33Z baconevi $
|
||||
*/
|
||||
|
||||
#ifndef _QSE_STX_ARRAY_H_
|
||||
#define _QSE_STX_ARRAY_H_
|
||||
|
||||
#include <qse/stx/stx.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
qse_word_t qse_stx_new_array (qse_stx_t* stx, qse_word_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -5,22 +5,6 @@
|
||||
#include "stx.h"
|
||||
#include <qse/cmn/str.h>
|
||||
|
||||
static int make_intrinsic_classes (qse_stx_t* stx);
|
||||
|
||||
static qse_word_t __make_classvar_dic (
|
||||
qse_stx_t* stx, qse_word_t class, const qse_char_t* names);
|
||||
static void __filein_kernel (qse_stx_t* stx);
|
||||
|
||||
static qse_word_t __count_names (const qse_char_t* str);
|
||||
static void __set_names (
|
||||
qse_stx_t* stx, qse_word_t* array, const qse_char_t* str);
|
||||
|
||||
static qse_word_t __count_subclasses (const qse_char_t* str);
|
||||
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);
|
||||
|
||||
struct class_info_t
|
||||
{
|
||||
const qse_char_t* name;
|
||||
@ -39,7 +23,7 @@ static class_info_t class_info[] =
|
||||
QSE_T("Object"),
|
||||
QSE_NULL,
|
||||
QSE_NULL,
|
||||
QSE_NULL,
|
||||
QSE_T("classvar1 classvar2")/*QSE_NULL TODO: delete this.....*/,
|
||||
QSE_NULL,
|
||||
SPEC_FIXED_WORD
|
||||
},
|
||||
@ -54,7 +38,7 @@ static class_info_t class_info[] =
|
||||
{
|
||||
QSE_T("Behavior"),
|
||||
QSE_T("Object"),
|
||||
QSE_T("spec methods superclass"),
|
||||
QSE_T("spec methods superclass subclasses"),
|
||||
QSE_NULL,
|
||||
QSE_NULL,
|
||||
SPEC_FIXED_WORD
|
||||
@ -280,164 +264,94 @@ 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 x;
|
||||
|
||||
QSE_ASSERT (REFISIDX(stx,stx->ref.class_string));
|
||||
QSE_ASSERT (!ISNIL(stx,stx->ref.class_string));
|
||||
|
||||
x = qse_stx_alloccharobj (stx, str, qse_strlen(str));
|
||||
if (x != stx->ref.nil) OBJCLASS(stx,x) = stx->ref.class_string;
|
||||
|
||||
return x;
|
||||
return qse_stx_instantiate (
|
||||
stx, stx->ref.class_string, QSE_NULL, str, qse_strlen(str));
|
||||
}
|
||||
|
||||
static int make_intrinsic_classes (qse_stx_t* stx)
|
||||
qse_word_t QSE_INLINE new_array (qse_stx_t* stx, qse_word_t capa)
|
||||
{
|
||||
class_info_t* p;
|
||||
qse_word_t n;
|
||||
|
||||
QSE_ASSERT (REFISIDX(stx,stx->ref.class_array));
|
||||
QSE_ASSERT (!ISNIL(stx,stx->ref.class_array));
|
||||
|
||||
for (p = class_info; p->name != QSE_NULL; p++)
|
||||
{
|
||||
qse_word_t classref;
|
||||
qse_stx_class_t* classptr;
|
||||
qse_word_t nfixed;
|
||||
|
||||
classref = qse_stx_findclass(stx, p->name);
|
||||
if (ISNIL(stx,classref))
|
||||
{
|
||||
classref = qse_stx_newclass (stx, p->name);
|
||||
if (ISNIL(stx,classref)) return NIL(stx);
|
||||
}
|
||||
|
||||
classptr = (qse_stx_class_t*)PTRBYREF(stx,classref);
|
||||
if (p->superclass)
|
||||
{
|
||||
classptr->superclass = qse_stx_findclass(stx,p->superclass);
|
||||
QSE_ASSERT (!ISNIL(stx,classptr->superclass));
|
||||
}
|
||||
|
||||
nfixed = 0;
|
||||
|
||||
/* resolve the number of fixed fields in the superclass chain */
|
||||
if (p->superclass)
|
||||
{
|
||||
qse_word_t superref;
|
||||
qse_stx_class_t* superptr;
|
||||
|
||||
qse_word_t metaref;
|
||||
qse_stx_metaclass_t* metaptr;
|
||||
|
||||
superref = qse_stx_findclass (stx, p->superclass);
|
||||
QSE_ASSERT (!ISNIL(stx,superref));
|
||||
|
||||
metaref = OBJCLASS(stx,classref);
|
||||
metaptr = (qse_stx_metaclass_t*)PTRBYREF(stx,metaref);
|
||||
metaptr->superclass = OBJCLASS(stx,superref);
|
||||
metaptr->instance_class = classref;
|
||||
|
||||
do
|
||||
{
|
||||
superptr = (qse_stx_class_t*)PTRBYREF(stx,superref);
|
||||
nfixed += SPEC_GETFIXED(REFTOINT(stx,superptr->spec));
|
||||
superref = superptr->superclass;
|
||||
}
|
||||
while (!ISNIL(stx,superref));
|
||||
}
|
||||
|
||||
/* add the number of instance variables to the number of
|
||||
* fixed fields */
|
||||
if (p->instance_variables)
|
||||
{
|
||||
nfixed += __count_names (p->instance_variables);
|
||||
classptr->variables =
|
||||
new_string (stx, p->instance_variables);
|
||||
if (ISNIL(stx,classptr->variables)) return -1;
|
||||
}
|
||||
|
||||
QSE_ASSERT (
|
||||
nfixed <= 0 ||
|
||||
(nfixed > 0 && (p->spec == SPEC_FIXED_WORD ||
|
||||
p->spec == SPEC_VARIABLE_WORD)));
|
||||
|
||||
classptr->spec = SPEC_MAKE (nfixed, p->spec);
|
||||
}
|
||||
|
||||
for (p = class_info; p->name != QSE_NULL; p++)
|
||||
{
|
||||
qse_word_t classref;
|
||||
qse_stx_class_t* classptr;
|
||||
|
||||
classref = qse_stx_findclass (stx, p->name);
|
||||
QSE_ASSERT (!ISNIL(stx,classref));
|
||||
|
||||
classptr = (qse_stx_class_t*)PTRBYREF(stx,classref);
|
||||
|
||||
if (p->class_variables != QSE_NULL)
|
||||
{
|
||||
classptr->class_variables =
|
||||
__make_classvar_dic(stx, classref, p->class_variables);
|
||||
|
||||
if (ISNIL(stx,classptr->class_variables)) return NIL(stx);
|
||||
}
|
||||
|
||||
/*
|
||||
TODO:
|
||||
if (p->pool_dictionaries != QSE_NULL) {
|
||||
classptr->pool_dictionaries =
|
||||
__make_pool_dictionary(stx, class, p->pool_dictionaries);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/* fill subclasses */
|
||||
for (p = class_info; p->name != QSE_NULL; p++)
|
||||
{
|
||||
qse_word_t classref;
|
||||
qse_stx_class_t* classptr;
|
||||
qse_word_t array;
|
||||
|
||||
n = __count_subclasses (p->name);
|
||||
array = qse_stx_newarray (stx, n);
|
||||
if (ISNIL(stx,array)) return NIL(stx);
|
||||
|
||||
__set_subclasses (stx, &WORDAT(stx,array,0), p->name);
|
||||
|
||||
classref = qse_stx_findclass (stx, p->name);
|
||||
QSE_ASSERT (!ISNIL(stx,classref));
|
||||
|
||||
classptr = (qse_stx_class_t*)PTRBYREF(stx,classref);
|
||||
classptr->subclasses = array;
|
||||
}
|
||||
|
||||
/* fill subclasses for metaclasses */
|
||||
for (p = class_info; p->name != QSE_NULL; p++)
|
||||
{
|
||||
qse_word_t classref;
|
||||
qse_stx_class_t* classptr;
|
||||
|
||||
qse_word_t metaref;
|
||||
qse_stx_metaclass_t* metaptr;
|
||||
|
||||
qse_word_t array;
|
||||
|
||||
n = __count_subclasses (p->name);
|
||||
array = qse_stx_new_array (stx, n);
|
||||
__set_metaclass_subclasses (stx, &WORDAT(stx,array,0), p->name);
|
||||
|
||||
classref = qse_stx_findclass (stx, p->name);
|
||||
QSE_ASSERT (!ISNIL(stx,classref));
|
||||
|
||||
metaref = OBJCLASS(stx,classref);
|
||||
metaptr = (qse_stx_metaclass_t*)PTRBYREF(stx,metaref);
|
||||
metaptr->subclasses = array;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return qse_stx_instantiate (
|
||||
stx, stx->ref.class_array, QSE_NULL, QSE_NULL, capa);
|
||||
}
|
||||
|
||||
static qse_word_t __count_names (const qse_char_t* str)
|
||||
qse_word_t QSE_INLINE new_systemdictionary (qse_stx_t* stx, qse_word_t capa)
|
||||
{
|
||||
QSE_ASSERT (REFISIDX(stx,stx->ref.class_systemdictionary));
|
||||
QSE_ASSERT (!ISNIL(stx,stx->ref.class_systemdictionary));
|
||||
|
||||
/* the system dictionary uses 1 slot dedicated for nil.
|
||||
* so we request to allocate 1 more slot than the given */
|
||||
return qse_stx_instantiate (
|
||||
stx, stx->ref.class_systemdictionary,
|
||||
QSE_NULL, QSE_NULL, capa + 1);
|
||||
}
|
||||
|
||||
qse_word_t new_class (qse_stx_t* stx, const qse_char_t* name)
|
||||
{
|
||||
qse_word_t meta, class, assoc;
|
||||
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 (ISNIL(stx,meta)) 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,SPEC_MAKE(QSE_STX_CLASS_SIZE,SPEC_FIXED_WORD));
|
||||
|
||||
/* the spec of the class is set later in __create_builtin_classes */
|
||||
class = qse_stx_allocwordobj (
|
||||
stx, QSE_NULL, QSE_STX_CLASS_SIZE, QSE_NULL, 0);
|
||||
OBJCLASS(stx,class) = meta;
|
||||
|
||||
class_name = qse_stx_newsymbol (stx, name);
|
||||
if (ISNIL(stx,class_name)) return stx->ref.nil;
|
||||
|
||||
WORDAT(stx,class,QSE_STX_CLASS_NAME) = class_name;
|
||||
WORDAT(stx,class,QSE_STX_CLASS_SPEC) = stx->ref.nil;
|
||||
|
||||
assoc = qse_stx_putdic (stx, stx->ref.sysdic, class_name, class);
|
||||
return (ISNIL(stx,assoc))? stx->ref.nil: class;
|
||||
}
|
||||
|
||||
qse_word_t find_class (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 (ISNIL(stx,assoc))
|
||||
{
|
||||
/*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_ASSOCIATION_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;
|
||||
}
|
||||
|
||||
static qse_word_t count_names (const qse_char_t* str)
|
||||
{
|
||||
qse_word_t n = 0;
|
||||
const qse_char_t* p = str;
|
||||
@ -458,30 +372,7 @@ static qse_word_t __count_names (const qse_char_t* str)
|
||||
return n;
|
||||
}
|
||||
|
||||
static void __set_names (
|
||||
qse_stx_t* stx, qse_word_t* array, const qse_char_t* str)
|
||||
{
|
||||
qse_word_t n = 0;
|
||||
const qse_char_t* p = str;
|
||||
const qse_char_t* name;
|
||||
|
||||
do
|
||||
{
|
||||
while (*p == QSE_T(' ') ||
|
||||
*p == QSE_T('\t')) p++;
|
||||
if (*p == QSE_T('\0')) break;
|
||||
|
||||
name = p;
|
||||
while (*p != QSE_T(' ') &&
|
||||
*p != QSE_T('\t') &&
|
||||
*p != QSE_T('\0')) p++;
|
||||
|
||||
array[n++] = qse_stx_newsymbolx (stx, name, p - name);
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
static qse_word_t __count_subclasses (const qse_char_t* str)
|
||||
static qse_word_t count_subclasses (const qse_char_t* str)
|
||||
{
|
||||
class_info_t* p;
|
||||
qse_word_t n = 0;
|
||||
@ -495,7 +386,7 @@ static qse_word_t __count_subclasses (const qse_char_t* str)
|
||||
return n;
|
||||
}
|
||||
|
||||
static void __set_subclasses (
|
||||
static void set_subclasses (
|
||||
qse_stx_t* stx, qse_word_t* array, const qse_char_t* str)
|
||||
{
|
||||
class_info_t* p;
|
||||
@ -505,13 +396,13 @@ static void __set_subclasses (
|
||||
{
|
||||
if (p->superclass == QSE_NULL) continue;
|
||||
if (qse_strcmp (str, p->superclass) != 0) continue;
|
||||
class = qse_stx_findclass (stx, p->name);
|
||||
class = find_class (stx, p->name);
|
||||
QSE_ASSERT (!ISNIL(stx,class));
|
||||
array[n++] = class;
|
||||
}
|
||||
}
|
||||
|
||||
static void __set_metaclass_subclasses (
|
||||
static void set_metaclass_subclasses (
|
||||
qse_stx_t* stx, qse_word_t* array, const qse_char_t* str)
|
||||
{
|
||||
class_info_t* p;
|
||||
@ -521,13 +412,13 @@ static void __set_metaclass_subclasses (
|
||||
{
|
||||
if (p->superclass == QSE_NULL) continue;
|
||||
if (qse_strcmp (str, p->superclass) != 0) continue;
|
||||
class = qse_stx_findclass (stx, p->name);
|
||||
class = find_class (stx, p->name);
|
||||
QSE_ASSERT (!ISNIL(stx,class));
|
||||
array[n++] = OBJCLASS(stx,class);
|
||||
}
|
||||
}
|
||||
|
||||
static qse_word_t __make_classvar_dic (
|
||||
static qse_word_t make_classvar_dic (
|
||||
qse_stx_t* stx, qse_word_t class, const qse_char_t* names)
|
||||
{
|
||||
qse_word_t dic, symbol, assoc;
|
||||
@ -535,10 +426,8 @@ static qse_word_t __make_classvar_dic (
|
||||
const qse_char_t* name;
|
||||
|
||||
/* TODO: how to implement temporary GC prevention....???? */
|
||||
dic = qse_stx_instantiate (
|
||||
stx, stx->ref.class_systemdictionary,
|
||||
QSE_NULL, QSE_NULL, __count_names(names));
|
||||
if (ISNIL(stx,dic)) return NIL(stx);
|
||||
dic = new_systemdictionary (stx, count_names(names));
|
||||
if (ISNIL(stx,dic)) return stx->ref.nil;
|
||||
|
||||
do
|
||||
{
|
||||
@ -552,25 +441,16 @@ static qse_word_t __make_classvar_dic (
|
||||
*p != QSE_T('\0')) p++;
|
||||
|
||||
symbol = qse_stx_newsymbolx (stx, name, p - name);
|
||||
if (ISNIL(stx,symbol)) return NIL(stx);
|
||||
if (ISNIL(stx,symbol)) return stx->ref.nil;
|
||||
|
||||
assoc =qse_stx_putdic (stx, dic, symbol, stx->ref.nil);
|
||||
if (ISNIL(stx,assoc)) return NIL(stx);
|
||||
assoc = qse_stx_putdic (stx, dic, symbol, stx->ref.nil);
|
||||
if (ISNIL(stx,assoc)) return stx->ref.nil;
|
||||
}
|
||||
while (1);
|
||||
|
||||
return dic;
|
||||
}
|
||||
|
||||
static void __filein_kernel (qse_stx_t* stx)
|
||||
{
|
||||
class_info_t* p;
|
||||
|
||||
for (p = class_info; p->name != QSE_NULL; p++) {
|
||||
/* TODO: */
|
||||
}
|
||||
}
|
||||
|
||||
static int sketch_nil (qse_stx_t* stx)
|
||||
{
|
||||
qse_stx_objidx_t idx;
|
||||
@ -597,12 +477,13 @@ static int sketch_nil (qse_stx_t* stx)
|
||||
ptr->h._class = stx->ref.nil; /* the class is yet to be set */
|
||||
ptr->h._backref = ref;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ALLOC_WORDOBJ_TO(stx,var,nflds,nvflds) QSE_BLOCK (\
|
||||
var = qse_stx_allocwordobj ((stx), QSE_NULL, (nflds), QSE_NULL, nvflds); \
|
||||
if ((var) == (stx)->ref.nil) return -1; \
|
||||
if (ISNIL(stx,(var))) return -1; \
|
||||
)
|
||||
|
||||
#define ADD_TO_SYSDIC(stx,key,value) QSE_BLOCK (\
|
||||
@ -611,12 +492,12 @@ static int sketch_nil (qse_stx_t* stx)
|
||||
|
||||
#define NEW_SYMBOL_TO(stx,var,name) QSE_BLOCK (\
|
||||
var = qse_stx_newsymbol ((stx), name); \
|
||||
if (var == (stx)->ref.nil) return -1; \
|
||||
if (ISNIL(stx,(var))) return -1; \
|
||||
)
|
||||
|
||||
#define NEW_CLASS_TO(stx,var,name) QSE_BLOCK (\
|
||||
var = qse_stx_newclass ((stx), name); \
|
||||
if (var == (stx)->ref.nil) return -1; \
|
||||
var = new_class ((stx), name); \
|
||||
if (ISNIL(stx,(var))) return -1; \
|
||||
)
|
||||
|
||||
static int sketch_key_objects (qse_stx_t* stx)
|
||||
@ -628,21 +509,28 @@ static int sketch_key_objects (qse_stx_t* stx)
|
||||
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);
|
||||
ALLOC_WORDOBJ_TO (stx, stx->ref.false, 0, 0);
|
||||
QSE_ASSERT (REFISIDX(stx,stx->ref.nil));
|
||||
|
||||
/* create a symbol table partially initialized */
|
||||
/* Create a symbol table partially initialized.
|
||||
* Especially, the class of the symbol table is not set yet.
|
||||
* It must be corrected later */
|
||||
/* TODO: initial symbol table size */
|
||||
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);
|
||||
|
||||
/* global system dictionary */
|
||||
/* Create a global system dictionary partially initialized.
|
||||
* Especially, the class of the system dictionary is not set yet.
|
||||
* It must be corrected later */
|
||||
/* TODO: initial dictionary size */
|
||||
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);
|
||||
/* Set tally to 0 */
|
||||
WORDAT(stx,stx->ref.sysdic,QSE_STX_SYSTEMDICTIONARY_TALLY) = INTTOREF(stx,0);
|
||||
|
||||
/* Create a few critical class objects needed for maintaining
|
||||
* the symbol table and the system dictionary. At this point,
|
||||
* new_class() cannot be used yet. So the process is
|
||||
* pretty mundane as shown below. */
|
||||
|
||||
/* Symbol */
|
||||
ALLOC_WORDOBJ_TO (stx, stx->ref.class_symbol, QSE_STX_CLASS_SIZE, 0);
|
||||
@ -663,18 +551,18 @@ static int sketch_key_objects (qse_stx_t* stx)
|
||||
ALLOC_WORDOBJ_TO (stx, class_AssociationMeta, QSE_STX_METACLASS_SIZE, 0);
|
||||
|
||||
/* (Symbol class) setClass: Metaclass */
|
||||
QSE_STX_OBJCLASS(stx,class_SymbolMeta) = stx->ref.class_metaclass;
|
||||
OBJCLASS(stx,class_SymbolMeta) = stx->ref.class_metaclass;
|
||||
/* (Metaclass class) setClass: Metaclass */
|
||||
QSE_STX_OBJCLASS(stx,class_MetaclassMeta) = stx->ref.class_metaclass;
|
||||
OBJCLASS(stx,class_MetaclassMeta) = stx->ref.class_metaclass;
|
||||
/* (Association class) setClass: Metaclass */
|
||||
QSE_STX_OBJCLASS(stx,class_AssociationMeta) = stx->ref.class_metaclass;
|
||||
OBJCLASS(stx,class_AssociationMeta) = stx->ref.class_metaclass;
|
||||
|
||||
/* Symbol setClass: (Symbol class) */
|
||||
QSE_STX_OBJCLASS(stx,stx->ref.class_symbol) = class_SymbolMeta;
|
||||
OBJCLASS(stx,stx->ref.class_symbol) = class_SymbolMeta;
|
||||
/* Metaclass setClass: (Metaclass class) */
|
||||
QSE_STX_OBJCLASS(stx,stx->ref.class_metaclass) = class_MetaclassMeta;
|
||||
OBJCLASS(stx,stx->ref.class_metaclass) = class_MetaclassMeta;
|
||||
/* Association setClass: (Association class) */
|
||||
QSE_STX_OBJCLASS(stx,stx->ref.class_association) = class_AssociationMeta;
|
||||
OBJCLASS(stx,stx->ref.class_association) = class_AssociationMeta;
|
||||
|
||||
/* (Symbol class) setSpec: CLASS_SIZE */
|
||||
WORDAT(stx,class_SymbolMeta,QSE_STX_CLASS_SPEC) =
|
||||
@ -687,7 +575,7 @@ static int sketch_key_objects (qse_stx_t* stx)
|
||||
INTTOREF (stx, SPEC_MAKE(QSE_STX_CLASS_SIZE,SPEC_FIXED_WORD));
|
||||
|
||||
/* specs for class_metaclass, class_association,
|
||||
* class_symbol are set later in make_builtin_classes */
|
||||
* class_symbol are set later in make_intrinsic_classes */
|
||||
|
||||
/* #Symbol */
|
||||
NEW_SYMBOL_TO (stx, symbol_symbol, QSE_T("Symbol"));
|
||||
@ -703,6 +591,14 @@ static int sketch_key_objects (qse_stx_t* stx)
|
||||
/* Association setName: #Association */
|
||||
WORDAT(stx,stx->ref.class_association,QSE_STX_CLASS_NAME) = symbol_association;
|
||||
|
||||
/* propagte the spec field in advance */
|
||||
WORDAT(stx,stx->ref.class_symbol,QSE_STX_CLASS_SPEC) =
|
||||
INTTOREF (stx, SPEC_MAKE(0,SPEC_VARIABLE_CHAR));
|
||||
WORDAT(stx,stx->ref.class_metaclass,QSE_STX_CLASS_SPEC) =
|
||||
INTTOREF (stx, SPEC_MAKE(QSE_STX_METACLASS_SIZE,SPEC_FIXED_WORD));
|
||||
WORDAT(stx,stx->ref.class_association,QSE_STX_CLASS_SPEC) =
|
||||
INTTOREF (stx, SPEC_MAKE(QSE_STX_ASSOCIATION_SIZE,SPEC_FIXED_WORD));
|
||||
|
||||
/* register class names into the system dictionary */
|
||||
ADD_TO_SYSDIC (stx, symbol_symbol, stx->ref.class_symbol);
|
||||
ADD_TO_SYSDIC (stx, symbol_metaclass, stx->ref.class_metaclass);
|
||||
@ -711,11 +607,12 @@ static int sketch_key_objects (qse_stx_t* stx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int make_key_classes (qse_stx_t* stx)
|
||||
static int make_key_classes (qse_stx_t* stx)
|
||||
{
|
||||
/* object, class, and array are precreated for easier instantiation
|
||||
* of intrinsic classes */
|
||||
* of intrinsic classes. */
|
||||
NEW_CLASS_TO (stx, stx->ref.class_object, QSE_T("Object"));
|
||||
NEW_CLASS_TO (stx, stx->ref.class_undefinedobject, QSE_T("UndefinedObject"));
|
||||
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"));
|
||||
@ -726,65 +623,272 @@ int make_key_classes (qse_stx_t* stx)
|
||||
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"));
|
||||
|
||||
/* set the spec field in advance so that new_string() and new_array()
|
||||
* can call qse_stx_instantiate() from this point onwards */
|
||||
WORDAT(stx,stx->ref.class_string,QSE_STX_CLASS_SPEC) =
|
||||
INTTOREF (stx, SPEC_MAKE(0,SPEC_VARIABLE_CHAR));
|
||||
WORDAT(stx,stx->ref.class_array,QSE_STX_CLASS_SPEC) =
|
||||
INTTOREF (stx, SPEC_MAKE(0,SPEC_VARIABLE_WORD));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_class_of_more_key_objects (qse_stx_t* stx)
|
||||
{
|
||||
/* nil setClass: UndefinedObject */
|
||||
OBJCLASS(stx,stx->ref.nil) = stx->ref.class_undefinedobject;
|
||||
|
||||
/* sysdic(Smalltalk) setClass: SystemDictionary */
|
||||
OBJCLASS(stx,stx->ref.sysdic) = stx->ref.class_systemdictionary;
|
||||
|
||||
/* symtab setClass: SystemSymbolTable */
|
||||
OBJCLASS(stx,stx->ref.symtab) = stx->ref.class_systemsymboltable;
|
||||
}
|
||||
|
||||
static int make_intrinsic_classes (qse_stx_t* stx)
|
||||
{
|
||||
class_info_t* p;
|
||||
|
||||
QSE_ASSERT (!ISNIL(stx,stx->ref.class_array));
|
||||
|
||||
for (p = class_info; p->name != QSE_NULL; p++)
|
||||
{
|
||||
qse_word_t classref;
|
||||
qse_stx_class_t* classptr;
|
||||
qse_word_t nfixed;
|
||||
qse_word_t spec;
|
||||
|
||||
classref = find_class(stx, p->name);
|
||||
if (ISNIL(stx,classref))
|
||||
{
|
||||
classref = new_class (stx, p->name);
|
||||
if (ISNIL(stx,classref)) return stx->ref.nil;
|
||||
}
|
||||
|
||||
classptr = (qse_stx_class_t*)PTRBYREF(stx,classref);
|
||||
if (p->superclass)
|
||||
{
|
||||
classptr->superclass = find_class(stx,p->superclass);
|
||||
QSE_ASSERT (!ISNIL(stx,classptr->superclass));
|
||||
}
|
||||
|
||||
nfixed = 0;
|
||||
|
||||
/* resolve the number of fixed fields in the superclass chain */
|
||||
if (p->superclass)
|
||||
{
|
||||
qse_word_t superref;
|
||||
qse_stx_class_t* superptr;
|
||||
|
||||
qse_word_t metaref;
|
||||
qse_stx_metaclass_t* metaptr;
|
||||
|
||||
superref = find_class (stx, p->superclass);
|
||||
QSE_ASSERT (!ISNIL(stx,superref));
|
||||
|
||||
metaref = OBJCLASS(stx,classref);
|
||||
metaptr = (qse_stx_metaclass_t*)PTRBYREF(stx,metaref);
|
||||
metaptr->superclass = OBJCLASS(stx,superref);
|
||||
metaptr->instance_class = classref;
|
||||
|
||||
do
|
||||
{
|
||||
superptr = (qse_stx_class_t*)PTRBYREF(stx,superref);
|
||||
nfixed += SPEC_GETFIXED(REFTOINT(stx,superptr->spec));
|
||||
superref = superptr->superclass;
|
||||
}
|
||||
while (!ISNIL(stx,superref));
|
||||
}
|
||||
|
||||
/* add the number of instance variables to the number of
|
||||
* fixed fields */
|
||||
if (p->instance_variables)
|
||||
{
|
||||
nfixed += count_names (p->instance_variables);
|
||||
classptr->variables =
|
||||
new_string (stx, p->instance_variables);
|
||||
if (ISNIL(stx,classptr->variables)) return -1;
|
||||
}
|
||||
|
||||
QSE_ASSERT (
|
||||
nfixed <= 0 ||
|
||||
(nfixed > 0 && (p->spec == SPEC_FIXED_WORD ||
|
||||
p->spec == SPEC_VARIABLE_WORD)));
|
||||
|
||||
spec = INTTOREF (stx, SPEC_MAKE (nfixed, p->spec));
|
||||
|
||||
QSE_ASSERTX (ISNIL(stx,classptr->spec) || classptr->spec == spec,
|
||||
"If the specfication field is already set before this function, "
|
||||
"the specification in the class information table must match it. "
|
||||
"Otherwise, something is very wrong");
|
||||
|
||||
classptr->spec = spec;
|
||||
}
|
||||
|
||||
/* make class variable dictionaries and pool dictionaries */
|
||||
for (p = class_info; p->name; p++)
|
||||
{
|
||||
qse_word_t classref;
|
||||
qse_stx_class_t* classptr;
|
||||
|
||||
classref = find_class (stx, p->name);
|
||||
QSE_ASSERT (!ISNIL(stx,classref));
|
||||
|
||||
classptr = (qse_stx_class_t*)PTRBYREF(stx,classref);
|
||||
|
||||
if (p->class_variables)
|
||||
{
|
||||
classptr->class_variables =
|
||||
make_classvar_dic(stx, classref, p->class_variables);
|
||||
if (ISNIL(stx,classptr->class_variables)) return stx->ref.nil;
|
||||
}
|
||||
|
||||
/*
|
||||
TODO:
|
||||
if (p->pool_dictionaries != QSE_NULL) {
|
||||
classptr->pool_dictionaries =
|
||||
__make_pool_dictionary(stx, class, p->pool_dictionaries);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/* fill subclasses */
|
||||
for (p = class_info; p->name != QSE_NULL; p++)
|
||||
{
|
||||
qse_word_t classref;
|
||||
qse_stx_class_t* classptr;
|
||||
qse_word_t array;
|
||||
qse_word_t n;
|
||||
|
||||
n = count_subclasses (p->name);
|
||||
array = new_array (stx, n);
|
||||
if (ISNIL(stx,array)) return -1;
|
||||
|
||||
set_subclasses (stx, &WORDAT(stx,array,0), p->name);
|
||||
|
||||
classref = find_class (stx, p->name);
|
||||
QSE_ASSERT (!ISNIL(stx,classref));
|
||||
|
||||
classptr = (qse_stx_class_t*)PTRBYREF(stx,classref);
|
||||
classptr->subclasses = array;
|
||||
}
|
||||
|
||||
/* fill subclasses for metaclasses */
|
||||
for (p = class_info; p->name != QSE_NULL; p++)
|
||||
{
|
||||
qse_word_t classref;
|
||||
|
||||
qse_word_t metaref;
|
||||
qse_stx_metaclass_t* metaptr;
|
||||
|
||||
qse_word_t array;
|
||||
qse_word_t n;
|
||||
|
||||
n = count_subclasses (p->name);
|
||||
array = new_array (stx, n);
|
||||
if (ISNIL(stx,array)) return -1;
|
||||
|
||||
set_metaclass_subclasses (stx, &WORDAT(stx,array,0), p->name);
|
||||
|
||||
classref = find_class (stx, p->name);
|
||||
QSE_ASSERT (!ISNIL(stx,classref));
|
||||
|
||||
metaref = OBJCLASS(stx,classref);
|
||||
metaptr = (qse_stx_metaclass_t*)PTRBYREF(stx,metaref);
|
||||
metaptr->subclasses = array;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void make_metaclass_top_hierarchy (qse_stx_t* stx)
|
||||
{
|
||||
qse_word_t metaclass_of_object;
|
||||
|
||||
/* make the superclass of Object class to be Class */
|
||||
|
||||
/* metaclass_of_object := Object class */
|
||||
metaclass_of_object = OBJCLASS (stx, stx->ref.class_object);
|
||||
|
||||
/* (Object class) setSuperclass: Class */
|
||||
WORDAT(stx,metaclass_of_object,QSE_STX_METACLASS_SUPERCLASS) = stx->ref.class_class;
|
||||
|
||||
/* Set the instance class for Object here as it is not
|
||||
* set in make_intrisic_classes */
|
||||
WORDAT(stx,metaclass_of_object,QSE_STX_METACLASS_INSTANCE_CLASS) = stx->ref.class_object;
|
||||
}
|
||||
|
||||
|
||||
static int make_key_objects_accessible_by_name (qse_stx_t* stx)
|
||||
{
|
||||
qse_word_t tmp;
|
||||
|
||||
#if 0
|
||||
/* create #nil, #true, #false */
|
||||
NEW_SYMBOL_TO (stx, tmp, QSE_T("nil"));
|
||||
NEW_SYMBOL_TO (stx, tmp, QSE_T("true"));
|
||||
NEW_SYMBOL_TO (stx, tmp, QSE_T("false"));
|
||||
#endif
|
||||
|
||||
NEW_SYMBOL_TO (stx, tmp, QSE_T("Smalltalk"));
|
||||
/* Smalltalk at: #Smalltalk put: stx->ref.sysdic */
|
||||
ADD_TO_SYSDIC (stx, tmp, stx->ref.sysdic);
|
||||
|
||||
NEW_SYMBOL_TO (stx, tmp, QSE_T("SymbolTable"));
|
||||
/* Smalltalk at: #SymbolTable put: stx->ref.sysdic */
|
||||
ADD_TO_SYSDIC (stx, tmp, stx->ref.symtab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int make_true_and_false (qse_stx_t* stx)
|
||||
{
|
||||
stx->ref.true = qse_stx_instantiate (
|
||||
stx, find_class(stx,QSE_T("True")),
|
||||
QSE_NULL, QSE_NULL, 0
|
||||
);
|
||||
if (ISNIL(stx,stx->ref.true)) return -1;
|
||||
|
||||
stx->ref.false = qse_stx_instantiate (
|
||||
stx, find_class(stx,QSE_T("False")),
|
||||
QSE_NULL, QSE_NULL, 0
|
||||
);
|
||||
if (ISNIL(stx,stx->ref.false)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void filein_kernel_source (qse_stx_t* stx)
|
||||
{
|
||||
class_info_t* p;
|
||||
|
||||
for (p = class_info; p->name != QSE_NULL; p++)
|
||||
{
|
||||
/* TODO: */
|
||||
}
|
||||
}
|
||||
|
||||
int qse_stx_boot (qse_stx_t* stx)
|
||||
{
|
||||
qse_word_t symbol_smalltalk;
|
||||
qse_word_t object_meta;
|
||||
|
||||
/* create a partially initialized nil object for bootstrapping */
|
||||
if (sketch_nil (stx) <= -1) goto oops;
|
||||
/* create nil, true, false references */
|
||||
if (sketch_nil (stx) <= -1) return -1;
|
||||
|
||||
/* continue intializing other key objects */
|
||||
if (sketch_key_objects (stx) <= -1) goto oops;
|
||||
if (sketch_key_objects (stx) <= -1) return -1;
|
||||
|
||||
if (make_key_classes (stx) <= -1) goto oops;
|
||||
if (make_key_classes (stx) <= -1) return -1;
|
||||
|
||||
if (make_intrisic_classes (stx) <= -1) goto oops;
|
||||
set_class_of_more_key_objects (stx);
|
||||
|
||||
if (make_intrinsic_classes (stx) <= -1) return -1;
|
||||
|
||||
make_metaclass_top_hierarchy (stx);
|
||||
|
||||
if (make_key_objects_accessible_by_name (stx) <= -1) return -1;
|
||||
|
||||
if (make_true_and_false (stx) <= -1) return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
/* (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;
|
||||
/* instance class for Object is set here as it is not
|
||||
* set in make_intrisic_classes */
|
||||
QSE_STX_WORD_AT(stx,object_meta,QSE_STX_METACLASS_INSTANCE_CLASS) = stx->class_object;
|
||||
|
||||
/* for some fun here */
|
||||
{
|
||||
qse_word_t array;
|
||||
array = qse_stx_new_array (stx, 1);
|
||||
QSE_STX_WORD_AT(stx,array,0) = object_meta;
|
||||
QSE_STX_WORD_AT(stx,stx->class_class,QSE_STX_CLASS_SUBCLASSES) = array;
|
||||
}
|
||||
|
||||
/* more initialization */
|
||||
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 */
|
||||
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 */
|
||||
OBJCLASS(stx,stx->ref.nil) = qse_stx_findclass (stx, QSE_T("UndefinedObject"));
|
||||
/* true setClass: True */
|
||||
OBJCLASS(stx,stx->ref.true) = qse_stx_findclass (stx, QSE_T("True"));
|
||||
/* fales setClass: False */
|
||||
OBJCLASS(stx,stx->ref.false) = qse_stx_findclass (stx, QSE_T("False"));
|
||||
|
||||
__filein_kernel (stx);
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
oops:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1,66 +1,9 @@
|
||||
/*
|
||||
* $Id: class.c 118 2008-03-03 11:21:33Z baconevi $
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "stx.h"
|
||||
|
||||
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,SPEC_MAKE(QSE_STX_CLASS_SIZE,SPEC_FIXED_WORD));
|
||||
|
||||
/* the spec of the class is set later in __create_builtin_classes */
|
||||
class = qse_stx_allocwordobj (
|
||||
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,
|
||||
@ -189,7 +132,6 @@ qse_word_t qse_stx_instantiate (
|
||||
qse_word_t spec, nflds, inst;
|
||||
int variable;
|
||||
|
||||
|
||||
QSE_ASSERT (REFISIDX(stx,classref));
|
||||
|
||||
/* don't instantiate a metaclass whose instance must be
|
||||
@ -197,6 +139,7 @@ qse_word_t qse_stx_instantiate (
|
||||
QSE_ASSERT (OBJCLASS(stx,classref) != stx->ref.class_metaclass);
|
||||
|
||||
classptr = (qse_stx_class_t*)PTRBYREF(stx,classref);
|
||||
qse_printf (QSE_T("instantiating ... %s\n"), ((qse_stx_charobj_t*)PTRBYREF(stx,classptr->name))->fld);
|
||||
QSE_ASSERT (REFISINT(stx,classptr->spec));
|
||||
|
||||
spec = REFTOINT(stx,classptr->spec);
|
||||
|
@ -56,8 +56,8 @@ typedef struct qse_stx_metaclass_t qse_stx_metaclass_t;
|
||||
#define SPEC_VARIABLE_BYTE 0x02
|
||||
#define SPEC_VARIABLE_CHAR 0x03
|
||||
|
||||
#define SPEC_MAKE(fixed,variable) \
|
||||
(((fixed) << SPEC_VARIABLE_BITS) | (variable))
|
||||
#define SPEC_MAKE(nfixed,variable) \
|
||||
(((nfixed) << SPEC_VARIABLE_BITS) | (variable))
|
||||
|
||||
#define SPEC_GETFIXED(spec) ((spec) >> SPEC_VARIABLE_BITS)
|
||||
|
||||
|
@ -10,15 +10,15 @@
|
||||
* Dictionary, on the contrary, can accept any object as a key.
|
||||
*/
|
||||
|
||||
struct qse_stx_assoc_t
|
||||
struct qse_stx_association_t
|
||||
{
|
||||
qse_stx_objhdr_t h;
|
||||
qse_word_t key;
|
||||
qse_word_t value;
|
||||
};
|
||||
typedef struct qse_stx_assoc_t qse_stx_assoc_t;
|
||||
typedef struct qse_stx_association_t qse_stx_association_t;
|
||||
|
||||
struct qse_stx_dic_t
|
||||
struct qse_stx_systemdictionary_t
|
||||
{
|
||||
qse_stx_objhdr_t h;
|
||||
qse_word_t tally;
|
||||
@ -26,30 +26,46 @@ struct qse_stx_dic_t
|
||||
/* variable part begins here */
|
||||
qse_word_t slot[1];
|
||||
};
|
||||
typedef struct qse_stx_dic_t qse_stx_dic_t;
|
||||
typedef struct qse_stx_systemdictionary_t qse_stx_systemdictionary_t;
|
||||
|
||||
static qse_word_t new_assoc (
|
||||
static qse_word_t new_association (
|
||||
qse_stx_t* stx, qse_word_t key, qse_word_t value)
|
||||
{
|
||||
#if 0
|
||||
qse_word_t x;
|
||||
|
||||
x = qse_stx_allocwordobj (
|
||||
stx, QSE_NULL, QSE_STX_ASSOC_SIZE, QSE_NULL, 0);
|
||||
if (x == stx->ref.nil) return stx->ref.nil;
|
||||
stx, QSE_NULL, QSE_STX_ASSOCIATION_SIZE, QSE_NULL, 0);
|
||||
if (ISNIL(stx,x)) return stx->ref.nil;
|
||||
|
||||
OBJCLASS(stx,x) = stx->ref.class_association;
|
||||
WORDAT(stx,x,QSE_STX_ASSOC_KEY) = key;
|
||||
WORDAT(stx,x,QSE_STX_ASSOC_VALUE) = value;
|
||||
WORDAT(stx,x,QSE_STX_ASSOCIATION_KEY) = key;
|
||||
WORDAT(stx,x,QSE_STX_ASSOCIATION_VALUE) = value;
|
||||
return x;
|
||||
#endif
|
||||
|
||||
qse_word_t x;
|
||||
|
||||
QSE_ASSERT (REFISIDX(stx,stx->ref.class_association));
|
||||
QSE_ASSERT (!ISNIL(stx,stx->ref.class_association));
|
||||
|
||||
x = qse_stx_instantiate (
|
||||
stx, stx->ref.class_association, QSE_NULL, QSE_NULL, 0);
|
||||
if (!ISNIL(stx,x))
|
||||
{
|
||||
WORDAT(stx,x,QSE_STX_ASSOCIATION_KEY) = key;
|
||||
WORDAT(stx,x,QSE_STX_ASSOCIATION_VALUE) = value;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static qse_word_t expand (qse_stx_t* stx, qse_word_t dic)
|
||||
{
|
||||
qse_word_t oldcapa, newdic, newcapa;
|
||||
qse_stx_dic_t* oldptr, * newptr;
|
||||
qse_stx_systemdictionary_t* oldptr, * newptr;
|
||||
|
||||
QSE_ASSERT (REFISIDX(stx,stx->ref.class_systemdictionary));
|
||||
QSE_ASSERT (stx->ref.class_systemdictionary != stx->ref.nil);
|
||||
QSE_ASSERT (!ISNIL(stx,stx->ref.class_systemdictionary));
|
||||
|
||||
QSE_ASSERTX (
|
||||
REFISIDX(stx,dic),
|
||||
@ -74,11 +90,11 @@ static qse_word_t expand (qse_stx_t* stx, qse_word_t dic)
|
||||
stx, OBJCLASS(stx,dic),
|
||||
QSE_NULL, QSE_NULL, newcapa
|
||||
);
|
||||
if (newdic == stx->ref.nil) return stx->ref.nil;
|
||||
if (ISNIL(stx,newdic)) return stx->ref.nil;
|
||||
|
||||
/* get object pointers for easier access without using macros */
|
||||
oldptr = (qse_stx_dic_t*)PTRBYREF(stx,dic);
|
||||
newptr = (qse_stx_dic_t*)PTRBYREF(stx,newdic);
|
||||
oldptr = (qse_stx_systemdictionary_t*)PTRBYREF(stx,dic);
|
||||
newptr = (qse_stx_systemdictionary_t*)PTRBYREF(stx,newdic);
|
||||
newptr->tally = INTTOREF(stx,0);
|
||||
|
||||
QSE_ASSERT (newcapa == OBJSIZE(stx,newdic)-1);
|
||||
@ -89,12 +105,12 @@ static qse_word_t expand (qse_stx_t* stx, qse_word_t dic)
|
||||
qse_word_t assoc;
|
||||
|
||||
assoc = oldptr->slot[--oldcapa];
|
||||
if (assoc != stx->ref.nil)
|
||||
if (!ISNIL(stx,assoc))
|
||||
{
|
||||
qse_word_t index;
|
||||
|
||||
index = qse_stx_hashobj (stx, WORDAT(stx,assoc,QSE_STX_ASSOC_KEY)) % newcapa;
|
||||
while (newptr->slot[index] != stx->ref.nil)
|
||||
index = qse_stx_hashobj (stx, WORDAT(stx,assoc,QSE_STX_ASSOCIATION_KEY)) % newcapa;
|
||||
while (!ISNIL(stx,newptr->slot[index]))
|
||||
index = (index + 1) % newcapa;
|
||||
newptr->slot[index] = assoc;
|
||||
}
|
||||
@ -112,13 +128,13 @@ static qse_word_t find_basic_index (
|
||||
qse_stx_t* stx, qse_word_t dic, qse_word_t key)
|
||||
{
|
||||
qse_word_t capa, index;
|
||||
qse_stx_dic_t* dicptr;
|
||||
qse_stx_systemdictionary_t* dicptr;
|
||||
|
||||
/* ensure that dic is a system dictionary */
|
||||
QSE_ASSERT (REFISIDX(stx,dic));
|
||||
QSE_ASSERT (OBJTYPE(stx,dic) == WORDOBJ);
|
||||
QSE_ASSERT (dic == stx->ref.sysdic ||
|
||||
OBJCLASS(stx,key) == stx->ref.class_systemdictionary);
|
||||
OBJCLASS(stx,dic) == stx->ref.class_systemdictionary);
|
||||
|
||||
/* ensure that the key is a symbol */
|
||||
QSE_ASSERT (REFISIDX(stx,key));
|
||||
@ -128,16 +144,16 @@ static qse_word_t find_basic_index (
|
||||
capa = OBJSIZE(stx,dic) - 1; /* exclude the tally field */
|
||||
index = qse_stx_hashobj (stx, key) % capa;
|
||||
|
||||
dicptr = (qse_stx_dic_t*)PTRBYREF(stx,dic);
|
||||
dicptr = (qse_stx_systemdictionary_t*)PTRBYREF(stx,dic);
|
||||
|
||||
do
|
||||
{
|
||||
qse_word_t assoc, sym;
|
||||
|
||||
assoc = dicptr->slot[index];
|
||||
if (assoc == stx->ref.nil) break; /* not found */
|
||||
if (ISNIL(stx,assoc)) break; /* not found */
|
||||
|
||||
sym = WORDAT (stx, assoc, QSE_STX_ASSOC_KEY);
|
||||
sym = WORDAT (stx, assoc, QSE_STX_ASSOCIATION_KEY);
|
||||
|
||||
/* make sure that the key is a symbol */
|
||||
QSE_ASSERT (REFISIDX(stx,sym));
|
||||
@ -163,7 +179,7 @@ qse_word_t qse_stx_lookupdic (
|
||||
qse_stx_t* stx, qse_word_t dic, const qse_char_t* skey)
|
||||
{
|
||||
qse_word_t capa, index;
|
||||
qse_stx_dic_t* dicptr;
|
||||
qse_stx_systemdictionary_t* dicptr;
|
||||
|
||||
QSE_ASSERT (REFISIDX(stx,dic));
|
||||
QSE_ASSERT (OBJTYPE(stx,dic) == WORDOBJ);
|
||||
@ -173,16 +189,16 @@ qse_word_t qse_stx_lookupdic (
|
||||
capa = OBJSIZE(stx,dic) - 1; /* exclude the tally field */
|
||||
index = qse_stx_hashstr (stx, skey) % capa;
|
||||
|
||||
dicptr = (qse_stx_dic_t*)PTRBYREF(stx,dic);
|
||||
dicptr = (qse_stx_systemdictionary_t*)PTRBYREF(stx,dic);
|
||||
|
||||
do
|
||||
{
|
||||
qse_word_t assoc, keyref;
|
||||
|
||||
assoc = dicptr->slot[index];
|
||||
if (assoc == stx->ref.nil) break; /* not found */
|
||||
if (ISNIL(stx,assoc)) break; /* not found */
|
||||
|
||||
keyref = WORDAT(stx,assoc,QSE_STX_ASSOC_KEY);
|
||||
keyref = WORDAT(stx,assoc,QSE_STX_ASSOCIATION_KEY);
|
||||
|
||||
QSE_ASSERT (REFISIDX(stx,keyref));
|
||||
QSE_ASSERT (OBJCLASS(stx,keyref) == stx->ref.class_symbol);
|
||||
@ -209,13 +225,13 @@ qse_word_t qse_stx_putdic (
|
||||
qse_stx_t* stx, qse_word_t dic, qse_word_t key, qse_word_t value)
|
||||
{
|
||||
qse_word_t index, capa, tally, assoc;
|
||||
qse_stx_dic_t* dicptr;
|
||||
qse_stx_systemdictionary_t* dicptr;
|
||||
|
||||
/* the dicionary must have at least one slot excluding tally */
|
||||
QSE_ASSERT (OBJSIZE(stx,dic) > 1);
|
||||
|
||||
capa = OBJSIZE(stx,dic) - 1;
|
||||
dicptr = (qse_stx_dic_t*)PTRBYREF(stx,dic);
|
||||
dicptr = (qse_stx_systemdictionary_t*)PTRBYREF(stx,dic);
|
||||
|
||||
tally = REFTOINT(stx,dicptr->tally);
|
||||
index = find_basic_index (stx, dic, key) - 1;
|
||||
@ -223,7 +239,7 @@ qse_word_t qse_stx_putdic (
|
||||
|
||||
/*assoc = WORDAT(stx,dic,slot);*/
|
||||
|
||||
if (assoc == stx->ref.nil)
|
||||
if (ISNIL(stx,assoc))
|
||||
{
|
||||
/* the key is not found */
|
||||
|
||||
@ -235,10 +251,10 @@ 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 (expand (stx, dic) == stx->ref.nil) return stx->ref.nil;
|
||||
if (ISNIL(stx, expand (stx, dic))) return stx->ref.nil;
|
||||
|
||||
capa = OBJSIZE(stx,dic) - 1;
|
||||
dicptr = (qse_stx_dic_t*)PTRBYREF(stx,dic);
|
||||
dicptr = (qse_stx_systemdictionary_t*)PTRBYREF(stx,dic);
|
||||
/* tally must remain the same after expansion */
|
||||
QSE_ASSERT (tally == REFTOINT(stx,dicptr->tally));
|
||||
|
||||
@ -246,11 +262,11 @@ qse_word_t qse_stx_putdic (
|
||||
index = find_basic_index (stx, dic, key) - 1;
|
||||
/* the basic index returned must point to nil meaning
|
||||
* the key is not found */
|
||||
QSE_ASSERT (dicptr->slot[index] == stx->ref.nil);
|
||||
QSE_ASSERT (ISNIL(stx,dicptr->slot[index]));
|
||||
}
|
||||
|
||||
assoc = new_assoc (stx, key, value);
|
||||
if (assoc == stx->ref.nil) return stx->ref.nil;
|
||||
assoc = new_association (stx, key, value);
|
||||
if (ISNIL(stx,assoc)) return stx->ref.nil;
|
||||
|
||||
dicptr->slot[index] = assoc;
|
||||
dicptr->tally = INTTOREF(stx,tally+1);
|
||||
@ -258,7 +274,7 @@ qse_word_t qse_stx_putdic (
|
||||
else
|
||||
{
|
||||
/* found the key. change the value */
|
||||
WORDAT(stx,assoc,QSE_STX_ASSOC_VALUE) = value;
|
||||
WORDAT(stx,assoc,QSE_STX_ASSOCIATION_VALUE) = value;
|
||||
}
|
||||
|
||||
return assoc;
|
||||
|
@ -5,14 +5,14 @@
|
||||
#ifndef _QSE_LIB_STX_DIC_H_
|
||||
#define _QSE_LIB_STX_DIC_H_
|
||||
|
||||
#define QSE_STX_ASSOC_SIZE 2
|
||||
#define QSE_STX_ASSOC_KEY 0
|
||||
#define QSE_STX_ASSOC_VALUE 1
|
||||
#define QSE_STX_ASSOCIATION_SIZE 2
|
||||
#define QSE_STX_ASSOCIATION_KEY 0
|
||||
#define QSE_STX_ASSOCIATION_VALUE 1
|
||||
|
||||
/* 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
|
||||
#define QSE_STX_SYSTEMDICTIONARY_SIZE 1
|
||||
#define QSE_STX_SYSTEMDICTIONARY_TALLY 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
@ -1,194 +0,0 @@
|
||||
/*
|
||||
* $Id: dict.c 118 2008-03-03 11:21:33Z baconevi $
|
||||
*/
|
||||
|
||||
#include <qse/stx/dict.h>
|
||||
#include <qse/stx/object.h>
|
||||
#include <qse/stx/misc.h>
|
||||
|
||||
/* NOTE:
|
||||
* The code here implements SystemDictionary whose key is always a symbol.
|
||||
* Dictionary, on the contrary, can accept any object as a key.
|
||||
*/
|
||||
|
||||
qse_word_t __new_association (
|
||||
qse_stx_t* stx, qse_word_t key, qse_word_t value)
|
||||
{
|
||||
qse_word_t x;
|
||||
qse_word_t data[2];
|
||||
data[0] = key;
|
||||
data[1] = value;
|
||||
|
||||
x = qse_stx_alloc_word_object (
|
||||
stx, data, QSE_STX_ASSOCIATION_SIZE, QSE_NULL, 0);
|
||||
QSE_STX_CLASS(stx,x) = stx->class_association;
|
||||
return x;
|
||||
}
|
||||
|
||||
static qse_word_t __dict_find_slot (
|
||||
qse_stx_t* stx, qse_word_t dict, qse_word_t key)
|
||||
{
|
||||
qse_word_t size, hash, index, assoc, symbol;
|
||||
qse_stx_word_object_t* dict_obj;
|
||||
|
||||
qse_assert (!QSE_STX_ISSMALLINT(dict) &&
|
||||
QSE_STX_ISWORDOBJECT(stx, dict));
|
||||
qse_assert (dict == stx->smalltalk ||
|
||||
qse_stx_classof(stx,dict) == stx->class_system_dictionary);
|
||||
qse_assert (qse_stx_classof(stx,key) == stx->class_symbol);
|
||||
|
||||
size = QSE_STX_SIZE(stx,dict);
|
||||
hash = qse_stx_hash_object(stx, key);
|
||||
|
||||
/* consider tally, the only instance variable of a system dictionary */
|
||||
index = hash % (size - 1) + 1;
|
||||
|
||||
dict_obj = QSE_STX_WORD_OBJECT(stx,dict);
|
||||
|
||||
while (1) {
|
||||
assoc = dict_obj->data[index];
|
||||
if (assoc == stx->nil) break;
|
||||
|
||||
symbol = QSE_STX_WORD_AT(stx,assoc,QSE_STX_ASSOCIATION_KEY);
|
||||
qse_assert (qse_stx_classof(stx,symbol) == stx->class_symbol);
|
||||
|
||||
/* NOTE:
|
||||
* shallow comparison is enough for identity check
|
||||
* because a symbol can just be a key of a system dictionary
|
||||
*/
|
||||
if (qse_strxncmp(
|
||||
QSE_STX_DATA(stx,key), QSE_STX_SIZE(stx,key),
|
||||
QSE_STX_DATA(stx,symbol), QSE_STX_SIZE(stx,symbol)) == 0) break;
|
||||
|
||||
/* consider tally here too */
|
||||
index = index % (size - 1) + 1;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static void __grow_dict (qse_stx_t* stx, qse_word_t dict)
|
||||
{
|
||||
qse_word_t new, size, index, assoc;
|
||||
|
||||
/* WARNING:
|
||||
* if this assertion fails, adjust the initial size of the
|
||||
* system dictionary. i don't want this function to be called
|
||||
* during the bootstrapping.
|
||||
*/
|
||||
qse_assert (stx->class_system_dictionary != stx->nil);
|
||||
qse_assert (qse_stx_classof(stx,dict) == stx->class_system_dictionary);
|
||||
|
||||
size = QSE_STX_SIZE(stx,dict);
|
||||
new = qse_stx_instantiate (stx,
|
||||
QSE_STX_CLASS(stx,dict), QSE_NULL, QSE_NULL, (size - 1) * 2);
|
||||
QSE_STX_WORD_AT(stx,new,0) = QSE_STX_TO_SMALLINT(0);
|
||||
|
||||
for (index = 1; index < size; index++) {
|
||||
assoc = QSE_STX_WORD_AT(stx,dict,index);
|
||||
if (assoc == stx->nil) continue;
|
||||
|
||||
qse_stx_dict_put (stx, new,
|
||||
QSE_STX_WORD_AT(stx,assoc,QSE_STX_ASSOCIATION_KEY),
|
||||
QSE_STX_WORD_AT(stx,assoc,QSE_STX_ASSOCIATION_VALUE));
|
||||
}
|
||||
|
||||
/* TODO: explore if dict can be immediately destroyed. */
|
||||
|
||||
qse_assert (qse_sizeof(qse_stx_object_t*) == qse_sizeof(qse_uint_t));
|
||||
|
||||
QSE_SWAP (
|
||||
QSE_STX_OBJPTR(stx,dict),
|
||||
QSE_STX_OBJPTR(stx,new),
|
||||
qse_stx_object_t*,
|
||||
qse_uint_t
|
||||
);
|
||||
}
|
||||
|
||||
qse_word_t qse_stx_dict_lookup (
|
||||
qse_stx_t* stx, qse_word_t dict, const qse_char_t* key)
|
||||
{
|
||||
qse_word_t size, hash, index, assoc, symbol;
|
||||
qse_stx_word_object_t* dict_obj;
|
||||
|
||||
qse_assert (!QSE_STX_ISSMALLINT(dict) &&
|
||||
QSE_STX_ISWORDOBJECT(stx, dict));
|
||||
qse_assert (dict == stx->smalltalk ||
|
||||
qse_stx_classof(stx,dict) == stx->class_system_dictionary);
|
||||
|
||||
size = QSE_STX_SIZE(stx,dict);
|
||||
hash = qse_stx_hash(key, qse_strlen(key) * qse_sizeof(qse_char_t));
|
||||
|
||||
/* consider tally, the only instance variable of a system dictionary */
|
||||
index = hash % (size - 1) + 1;
|
||||
|
||||
dict_obj = QSE_STX_WORD_OBJECT(stx,dict);
|
||||
|
||||
while (1)
|
||||
{
|
||||
assoc = dict_obj->data[index];
|
||||
if (assoc == stx->nil) break;
|
||||
|
||||
symbol = QSE_STX_WORD_AT(stx,assoc,QSE_STX_ASSOCIATION_KEY);
|
||||
qse_assert (qse_stx_classof(stx,symbol) == stx->class_symbol);
|
||||
|
||||
if (qse_strxcmp (QSE_STX_DATA(stx,symbol),
|
||||
QSE_STX_SIZE(stx,symbol), key) == 0) break;
|
||||
|
||||
/* consider tally here too */
|
||||
index = index % (size - 1) + 1;
|
||||
}
|
||||
|
||||
return QSE_STX_WORD_AT(stx,dict,index);
|
||||
}
|
||||
|
||||
qse_word_t qse_stx_dict_get (qse_stx_t* stx, qse_word_t dict, qse_word_t key)
|
||||
{
|
||||
return QSE_STX_WORD_AT(stx,dict,__dict_find_slot(stx, dict, key));
|
||||
}
|
||||
|
||||
qse_word_t qse_stx_dict_put (
|
||||
qse_stx_t* stx, qse_word_t dict, qse_word_t key, qse_word_t value)
|
||||
{
|
||||
qse_word_t slot, capa, tally, assoc;
|
||||
|
||||
/* the dictionary must have at least one slot excluding tally */
|
||||
qse_assert (QSE_STX_SIZE(stx,dict) > 1);
|
||||
|
||||
capa = QSE_STX_SIZE(stx,dict) - 1;
|
||||
tally = QSE_STX_FROMSMALLINT(QSE_STX_WORD_AT(stx,dict,0));
|
||||
if (capa <= tally + 1)
|
||||
{
|
||||
__grow_dict (stx, dict);
|
||||
/* refresh tally */
|
||||
tally = QSE_STX_FROMSMALLINT(QSE_STX_WORD_AT(stx,dict,0));
|
||||
}
|
||||
|
||||
slot = __dict_find_slot (stx, dict, key);
|
||||
|
||||
assoc = QSE_STX_WORD_AT(stx,dict,slot);
|
||||
if (assoc == stx->nil)
|
||||
{
|
||||
QSE_STX_WORD_AT(stx,dict,slot) =
|
||||
__new_association (stx, key, value);
|
||||
QSE_STX_WORD_AT(stx,dict,0) = QSE_STX_TO_SMALLINT(tally + 1);
|
||||
}
|
||||
else QSE_STX_WORD_AT(stx,assoc,QSE_STX_ASSOCIATION_VALUE) = value;
|
||||
|
||||
return QSE_STX_WORD_AT(stx,dict,slot);
|
||||
}
|
||||
|
||||
void qse_stx_dict_traverse (
|
||||
qse_stx_t* stx, qse_word_t dict,
|
||||
void (*func) (qse_stx_t*,qse_word_t,void*), void* data)
|
||||
{
|
||||
qse_word_t index, assoc;
|
||||
qse_word_t size = QSE_STX_SIZE(stx,dict);
|
||||
|
||||
for (index = 1; index < size; index++) {
|
||||
assoc = QSE_STX_WORD_AT(stx,dict,index);
|
||||
if (assoc == stx->nil) continue;
|
||||
func (stx, assoc, data);
|
||||
}
|
||||
}
|
||||
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* $Id: dict.h 118 2008-03-03 11:21:33Z baconevi $
|
||||
*/
|
||||
|
||||
#ifndef _QSE_STX_DICT_H_
|
||||
#define _QSE_STX_DICT_H_
|
||||
|
||||
#include <qse/stx/stx.h>
|
||||
|
||||
#define QSE_STX_ASSOCIATION_SIZE 2
|
||||
#define QSE_STX_ASSOCIATION_KEY 0
|
||||
#define QSE_STX_ASSOCIATION_VALUE 1
|
||||
|
||||
struct qse_stx_association_t
|
||||
{
|
||||
qse_stx_objhdr_t header;
|
||||
qse_word_t key;
|
||||
qse_word_t value;
|
||||
};
|
||||
|
||||
typedef struct qse_stx_association_t qse_stx_association_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
|
||||
qse_word_t qse_stx_dict_lookup (
|
||||
qse_stx_t* stx, qse_word_t dict, const qse_char_t* key);
|
||||
qse_word_t qse_stx_dict_get (
|
||||
qse_stx_t* stx, qse_word_t dict, qse_word_t key);
|
||||
qse_word_t qse_stx_dict_put (
|
||||
qse_stx_t* stx, qse_word_t dict, qse_word_t key, qse_word_t value);
|
||||
void qse_stx_dict_traverse (
|
||||
qse_stx_t* stx, qse_word_t dict,
|
||||
void (*func) (qse_stx_t*,qse_word_t,void*), void* data);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* $Id: memory.c 118 2008-03-03 11:21:33Z baconevi $
|
||||
*/
|
||||
|
||||
#include <qse/stx/memory.h>
|
||||
#include <qse/stx/misc.h>
|
||||
|
||||
qse_stx_memory_t* qse_stx_memory_open (
|
||||
qse_stx_memory_t* mem, qse_word_t capacity)
|
||||
{
|
||||
qse_stx_object_t** slots;
|
||||
qse_word_t n;
|
||||
|
||||
qse_assert (capacity > 0);
|
||||
if (mem == QSE_NULL) {
|
||||
mem = (qse_stx_memory_t*)qse_malloc(qse_sizeof(qse_stx_memory_t));
|
||||
if (mem == QSE_NULL) return QSE_NULL;
|
||||
mem->__dynamic = qse_true;
|
||||
}
|
||||
else mem->__dynamic = qse_false;
|
||||
|
||||
slots = (qse_stx_object_t**)qse_malloc (
|
||||
capacity * qse_sizeof(qse_stx_object_t*));
|
||||
if (slots == QSE_NULL) {
|
||||
if (mem->__dynamic) qse_free (mem);
|
||||
mem = QSE_NULL;
|
||||
}
|
||||
|
||||
mem->capacity = capacity;
|
||||
mem->slots = slots;
|
||||
|
||||
/* weave the free slot list */
|
||||
mem->free = &slots[0];
|
||||
for (n = 0; n < capacity - 1; n++) {
|
||||
mem->slots[n] = (qse_stx_object_t*)&mem->slots[n + 1];
|
||||
}
|
||||
mem->slots[n] = QSE_NULL;
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
void qse_stx_memory_close (qse_stx_memory_t* mem)
|
||||
{
|
||||
/* TODO: free all linked objects... */
|
||||
|
||||
qse_free (mem->slots);
|
||||
mem->capacity = 0;
|
||||
mem->slots = QSE_NULL;
|
||||
mem->free = QSE_NULL;
|
||||
if (mem->__dynamic) qse_free (mem);
|
||||
}
|
||||
|
||||
void qse_stx_memory_gc (qse_stx_memory_t* mem)
|
||||
{
|
||||
/* TODO: implement this function */
|
||||
}
|
||||
|
||||
qse_word_t qse_stx_memory_alloc (qse_stx_memory_t* mem, qse_word_t nbytes)
|
||||
{
|
||||
qse_stx_object_t** slot;
|
||||
qse_stx_object_t* object;
|
||||
|
||||
/* find the free object slot */
|
||||
if (mem->free == QSE_NULL) {
|
||||
qse_stx_memory_gc (mem);
|
||||
if (mem->free == QSE_NULL) return mem->capacity;;
|
||||
}
|
||||
|
||||
object = (qse_stx_object_t*)qse_malloc (nbytes);
|
||||
if (object == QSE_NULL) {
|
||||
qse_stx_memory_gc (mem);
|
||||
object = (qse_stx_object_t*)qse_malloc (nbytes);
|
||||
/*if (object == QSE_NULL) return mem->capacity;*/
|
||||
if (object == QSE_NULL) {
|
||||
qse_assert (QSE_T("MEMORY ALLOCATION ERROR\n") == QSE_NULL);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
slot = mem->free;
|
||||
mem->free = (qse_stx_object_t**)*slot;
|
||||
*slot = object;
|
||||
|
||||
return (qse_word_t)(slot - mem->slots);
|
||||
}
|
||||
|
||||
void qse_stx_memory_dealloc (qse_stx_memory_t* mem, qse_word_t object_index)
|
||||
{
|
||||
/*
|
||||
* THIS IS PRIMITIVE LOW-LEVEL DEALLOC. THIS WILL NOT
|
||||
* DEALLOCATE MEMORY ALLOCATED FOR ITS INSTANCE VARIABLES.
|
||||
*/
|
||||
|
||||
qse_free (mem->slots[object_index]);
|
||||
mem->slots[object_index] = (qse_stx_object_t*)mem->free;
|
||||
mem->free = &mem->slots[object_index];
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* $Id: memory.h 118 2008-03-03 11:21:33Z baconevi $
|
||||
*/
|
||||
|
||||
#ifndef _QSE_STX_MEMORY_H_
|
||||
#define _QSE_STX_MEMORY_H_
|
||||
|
||||
#include <qse/stx/stx.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
qse_stx_memory_t* qse_stx_initmem (
|
||||
qse_stx_memory_t* mem,
|
||||
qse_word_t capacity
|
||||
);
|
||||
|
||||
void qse_stx_finimem (
|
||||
qse_stx_memory_t* mem
|
||||
);
|
||||
|
||||
void qse_stx_gcmem (
|
||||
qse_stx_memory_t* mem
|
||||
);
|
||||
|
||||
qse_word_t qse_stx_alloc (
|
||||
qse_stx_memory_t* mem, qse_word_t size
|
||||
);
|
||||
|
||||
void qse_stx_memory_dealloc (
|
||||
qse_stx_memory_t* mem, qse_word_t object_index
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1008,39 +1008,47 @@ static int __parse_primary_ident (
|
||||
|
||||
*is_super = qse_false;
|
||||
|
||||
if (qse_strcmp(ident, QSE_T("self")) == 0) {
|
||||
if (qse_strcmp(ident, QSE_T("self")) == 0)
|
||||
{
|
||||
EMIT_CODE (parser, PUSH_RECEIVER);
|
||||
return 0;
|
||||
}
|
||||
else if (qse_strcmp(ident, QSE_T("super")) == 0) {
|
||||
else if (qse_strcmp(ident, QSE_T("super")) == 0)
|
||||
{
|
||||
*is_super = qse_true;
|
||||
EMIT_CODE (parser, PUSH_RECEIVER);
|
||||
return 0;
|
||||
}
|
||||
else if (qse_strcmp(ident, QSE_T("nil")) == 0) {
|
||||
else if (qse_strcmp(ident, QSE_T("nil")) == 0)
|
||||
{
|
||||
EMIT_CODE (parser, PUSH_NIL);
|
||||
return 0;
|
||||
}
|
||||
else if (qse_strcmp(ident, QSE_T("true")) == 0) {
|
||||
else if (qse_strcmp(ident, QSE_T("true")) == 0)
|
||||
{
|
||||
EMIT_CODE (parser, PUSH_TRUE);
|
||||
return 0;
|
||||
}
|
||||
else if (qse_strcmp(ident, QSE_T("false")) == 0) {
|
||||
else if (qse_strcmp(ident, QSE_T("false")) == 0)
|
||||
{
|
||||
EMIT_CODE (parser, PUSH_FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Refer to __parse_assignment for identifier lookup */
|
||||
|
||||
for (i = 0; i < parser->temporary_count; i++) {
|
||||
if (qse_strcmp(ident, parser->temporaries[i]) == 0) {
|
||||
for (i = 0; i < parser->temporary_count; i++)
|
||||
{
|
||||
if (qse_strcmp(ident, parser->temporaries[i]) == 0)
|
||||
{
|
||||
EMIT_PUSH_TEMPORARY_LOCATION (parser, i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (qse_stx_get_instance_variable_index (
|
||||
stx, parser->method_class, ident, &i) == 0) {
|
||||
stx, parser->method_class, ident, &i) == 0)
|
||||
{
|
||||
EMIT_PUSH_RECEIVER_VARIABLE (parser, i);
|
||||
return 0;
|
||||
}
|
||||
@ -1074,20 +1082,25 @@ static int __parse_block_constructor (qse_stx_parser_t* parser)
|
||||
* <block argument> ::= ':' identifier
|
||||
*/
|
||||
|
||||
if (parser->token.type == QSE_STX_TOKEN_COLON) {
|
||||
do {
|
||||
if (parser->token.type == QSE_STX_TOKEN_COLON)
|
||||
{
|
||||
do
|
||||
{
|
||||
GET_TOKEN (parser);
|
||||
|
||||
if (parser->token.type != QSE_STX_TOKEN_IDENT) {
|
||||
if (parser->token.type != QSE_STX_TOKEN_IDENT)
|
||||
{
|
||||
parser->error_code = QSE_STX_PARSER_ERROR_BLOCK_ARGUMENT_NAME;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO : store block arguments */
|
||||
GET_TOKEN (parser);
|
||||
} while (parser->token.type == QSE_STX_TOKEN_COLON);
|
||||
}
|
||||
while (parser->token.type == QSE_STX_TOKEN_COLON);
|
||||
|
||||
if (!__is_vbar_token(&parser->token)) {
|
||||
if (!__is_vbar_token(&parser->token))
|
||||
{
|
||||
parser->error_code = QSE_STX_PARSER_ERROR_BLOCK_ARGUMENT_LIST;
|
||||
return -1;
|
||||
}
|
||||
@ -1099,7 +1112,8 @@ static int __parse_block_constructor (qse_stx_parser_t* parser)
|
||||
if (__parse_temporaries(parser) == -1) return -1;
|
||||
if (__parse_block_statements(parser) == -1) return -1;
|
||||
|
||||
if (parser->token.type != QSE_STX_TOKEN_RBRACKET) {
|
||||
if (parser->token.type != QSE_STX_TOKEN_RBRACKET)
|
||||
{
|
||||
parser->error_code = QSE_STX_PARSER_ERROR_BLOCK_NOT_CLOSED;
|
||||
return -1;
|
||||
}
|
||||
@ -1123,7 +1137,8 @@ static int __parse_message_continuation (
|
||||
*/
|
||||
if (__parse_keyword_message(parser, is_super) == -1) return -1;
|
||||
|
||||
while (parser->token.type == QSE_STX_TOKEN_SEMICOLON) {
|
||||
while (parser->token.type == QSE_STX_TOKEN_SEMICOLON)
|
||||
{
|
||||
EMIT_CODE_TEST (parser, QSE_T("DoSpecial(DUP_RECEIVER(CASCADE))"), QSE_T(""));
|
||||
GET_TOKEN (parser);
|
||||
|
||||
|
@ -120,6 +120,7 @@ struct qse_stx_t
|
||||
qse_word_t class_association;
|
||||
|
||||
qse_word_t class_object;
|
||||
qse_word_t class_undefinedobject;
|
||||
qse_word_t class_class;
|
||||
qse_word_t class_array;
|
||||
qse_word_t class_bytearray;
|
||||
|
@ -49,7 +49,7 @@ static qse_word_t expand (qse_stx_t* stx, qse_word_t tabref)
|
||||
stx, OBJCLASS(stx,tabref),
|
||||
QSE_NULL, QSE_NULL, newcapa
|
||||
);
|
||||
if (ISNIL(stx,newtab)) return NIL(stx);
|
||||
if (ISNIL(stx,newtab)) return stx->ref.nil;
|
||||
|
||||
oldptr = (qse_stx_symtab_t*)PTRBYREF(stx,tabref);
|
||||
newptr = (qse_stx_symtab_t*)PTRBYREF(stx,newtab);
|
||||
@ -91,7 +91,7 @@ static qse_word_t expand (qse_stx_t* stx, qse_word_t 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_size_t len)
|
||||
{
|
||||
qse_stx_symtab_t* tabptr;
|
||||
qse_word_t symref;
|
||||
@ -135,7 +135,7 @@ static qse_word_t new_symbol (
|
||||
* make sure that it has at least one free slot left
|
||||
* after having added a new symbol. this is to help
|
||||
* traversal end at a nil slot if no entry is found. */
|
||||
if (ISNIL (stx, expand (stx, tabref))) return NIL(stx);
|
||||
if (ISNIL (stx, expand (stx, tabref))) return stx->ref.nil;
|
||||
|
||||
/* refresh the object pointer */
|
||||
tabptr = (qse_stx_symtab_t*)PTRBYREF(stx,tabref);
|
||||
@ -148,7 +148,7 @@ static qse_word_t new_symbol (
|
||||
QSE_ASSERT (tally == REFTOINT (stx, tabptr->tally));
|
||||
}
|
||||
|
||||
symref = qse_stx_alloccharobj (stx, name, qse_strlen(name));
|
||||
symref = qse_stx_alloccharobj (stx, name, len);
|
||||
if (!ISNIL(stx,symref))
|
||||
{
|
||||
OBJCLASS(stx,symref) = stx->ref.class_symbol;
|
||||
@ -161,7 +161,12 @@ static qse_word_t new_symbol (
|
||||
|
||||
qse_word_t qse_stx_newsymbol (qse_stx_t* stx, const qse_char_t* name)
|
||||
{
|
||||
return new_symbol (stx, stx->ref.symtab, name);
|
||||
return new_symbol (stx, stx->ref.symtab, name, qse_strlen(name));
|
||||
}
|
||||
|
||||
qse_word_t qse_stx_newsymbolx (qse_stx_t* stx, const qse_char_t* name, qse_size_t len)
|
||||
{
|
||||
return new_symbol (stx, stx->ref.symtab, name, len);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -19,6 +19,12 @@ qse_word_t qse_stx_newsymbol (
|
||||
const qse_char_t* name
|
||||
);
|
||||
|
||||
qse_word_t qse_stx_newsymbolx (
|
||||
qse_stx_t* stx,
|
||||
const qse_char_t* name,
|
||||
qse_size_t len
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* $Id: symbol.c 118 2008-03-03 11:21:33Z baconevi $
|
||||
*/
|
||||
|
||||
#include <qse/stx/symbol.h>
|
||||
#include <qse/stx/object.h>
|
||||
#include <qse/stx/misc.h>
|
||||
|
||||
static void __grow_symtab (qse_stx_t* stx)
|
||||
{
|
||||
qse_word_t capa, ncapa, i, j;
|
||||
qse_word_t* nspace;
|
||||
|
||||
capa = stx->symtab.capacity;
|
||||
ncapa = capa << 1;
|
||||
|
||||
nspace = (qse_word_t*)qse_malloc(qse_sizeof(qse_word_t) * ncapa);
|
||||
if (nspace == QSE_NULL)
|
||||
{
|
||||
/* TODO: handle memory error */
|
||||
}
|
||||
|
||||
for (i = 0; i < capa; i++)
|
||||
{
|
||||
qse_word_t x = stx->symtab.datum[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.capacity = ncapa;
|
||||
qse_free (stx->symtab.datum);
|
||||
stx->symtab.datum = nspace;
|
||||
}
|
||||
|
||||
qse_word_t qse_stx_new_symbol (qse_stx_t* stx, const qse_char_t* name)
|
||||
{
|
||||
return qse_stx_new_symbolx (stx, name, qse_strlen(name));
|
||||
}
|
||||
|
||||
qse_word_t qse_stx_new_symbolx (
|
||||
qse_stx_t* stx, const qse_char_t* name, qse_word_t len)
|
||||
{
|
||||
qse_word_t capa, hash, index, size, x;
|
||||
|
||||
capa = stx->symtab.capacity;
|
||||
size = stx->symtab.size;
|
||||
|
||||
if (capa <= size + 1)
|
||||
{
|
||||
__grow_symtab (stx);
|
||||
capa = stx->symtab.capacity;
|
||||
}
|
||||
|
||||
hash = qse_stx_strxhash(name,len);
|
||||
index = hash % stx->symtab.capacity;
|
||||
|
||||
while (1)
|
||||
{
|
||||
x = stx->symtab.datum[index];
|
||||
if (x == stx->nil)
|
||||
{
|
||||
/* insert a new item into an empty slot */
|
||||
x = qse_stx_alloc_char_objectx (stx, name, len);
|
||||
QSE_STX_CLASS(stx,x) = stx->class_symbol;
|
||||
stx->symtab.datum[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.capacity) + 1;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
void qse_stx_traverse_symbol_table (
|
||||
qse_stx_t* stx, void (*func) (qse_stx_t*,qse_word_t,void*), void* data)
|
||||
{
|
||||
qse_word_t index, x;
|
||||
|
||||
for (index = 0; index < stx->symtab.capacity; index++)
|
||||
{
|
||||
x = stx->symtab.datum[index];
|
||||
if (x != stx->nil) func (stx, x, data);
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* $Id: symbol.h 118 2008-03-03 11:21:33Z baconevi $
|
||||
*/
|
||||
|
||||
#ifndef _QSE_STX_SYMBOL_H_
|
||||
#define _QSE_STX_SYMBOL_H_
|
||||
|
||||
#include <qse/stx/stx.h>
|
||||
|
||||
#define QSE_STX_SYMLINK_SIZE 2
|
||||
#define QSE_STX_SYMLINK_LINK 0
|
||||
#define QSE_STX_SYMLINK_SYMBOL 1
|
||||
|
||||
struct qse_stx_symlink_t
|
||||
{
|
||||
qse_stx_objhdr_t header;
|
||||
qse_word_t link;
|
||||
qse_word_t symbol;
|
||||
};
|
||||
|
||||
typedef struct qse_stx_symlink_t qse_stx_symlink_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
qse_word_t qse_stx_new_symbol_link (qse_stx_t* stx, qse_word_t sym);
|
||||
|
||||
qse_word_t qse_stx_new_symbol (
|
||||
qse_stx_t* stx, const qse_char_t* name);
|
||||
qse_word_t qse_stx_new_symbolx (
|
||||
qse_stx_t* stx, const qse_char_t* name, qse_word_t len);
|
||||
void qse_stx_traverse_symbol_table (
|
||||
qse_stx_t* stx, void (*func) (qse_stx_t*,qse_word_t,void*), void* data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user