initial import

This commit is contained in:
2008-12-21 21:35:07 +00:00
parent 4c01ea1604
commit 4803bd861a
384 changed files with 24572 additions and 53621 deletions

18
qse/lib/stx/array.c Normal file
View File

@ -0,0 +1,18 @@
/*
* $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;
}

21
qse/lib/stx/array.h Normal file
View File

@ -0,0 +1,21 @@
/*
* $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

676
qse/lib/stx/bootstrp.c Normal file
View File

@ -0,0 +1,676 @@
/*
* $Id: bootstrp.c 118 2008-03-03 11:21:33Z baconevi $
*/
#include <qse/stx/bootstrp.h>
#include <qse/stx/symbol.h>
#include <qse/stx/class.h>
#include <qse/stx/object.h>
#include <qse/stx/dict.h>
#include <qse/stx/misc.h>
static void __create_bootstrapping_objects (qse_stx_t* stx);
static void __create_builtin_classes (qse_stx_t* stx);
static qse_word_t __make_classvar_dict (
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;
const qse_char_t* superclass;
const qse_char_t* instance_variables;
const qse_char_t* class_variables;
const qse_char_t* pool_dictionaries;
const int indexable;
};
typedef struct class_info_t class_info_t;
static class_info_t class_info[] =
{
{
QSE_T("Object"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("UndefinedObject"),
QSE_T("Object"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Behavior"),
QSE_T("Object"),
QSE_T("spec methods superclass"),
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Class"),
QSE_T("Behavior"),
QSE_T("name variables classVariables poolDictionaries"),
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Metaclass"),
QSE_T("Behavior"),
QSE_T("instanceClass"),
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Block"),
QSE_T("Object"),
QSE_T("context argCount argLoc bytePointer"),
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Boolean"),
QSE_T("Object"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("True"),
QSE_T("Boolean"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("False"),
QSE_T("Boolean"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Context"),
QSE_T("Object"),
QSE_T("stack stackTop receiver pc method"),
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Method"),
QSE_T("Object"),
QSE_T("text selector bytecodes tmpCount argCount"),
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_WORD_INDEXABLE
},
{
QSE_T("Magnitude"),
QSE_T("Object"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Association"),
QSE_T("Magnitude"),
QSE_T("key value"),
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Character"),
QSE_T("Magnitude"),
QSE_T("value"),
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Number"),
QSE_T("Magnitude"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Integer"),
QSE_T("Number"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("SmallInteger"),
QSE_T("Integer"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("LargeInteger"),
QSE_T("Integer"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_BYTE_INDEXABLE
},
{
QSE_T("Collection"),
QSE_T("Magnitude"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("IndexedCollection"),
QSE_T("Collection"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_T("Array"),
QSE_T("IndexedCollection"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_WORD_INDEXABLE
},
{
QSE_T("ByteArray"),
QSE_T("IndexedCollection"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_BYTE_INDEXABLE
},
{
QSE_T("Dictionary"),
QSE_T("IndexedCollection"),
QSE_T("tally"),
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_WORD_INDEXABLE
},
{
QSE_T("SystemDictionary"),
QSE_T("Dictionary"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_WORD_INDEXABLE
},
{
QSE_T("PoolDictionary"),
QSE_T("Dictionary"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_WORD_INDEXABLE
},
{
QSE_T("String"),
QSE_T("IndexedCollection"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_CHAR_INDEXABLE
},
{
QSE_T("Symbol"),
QSE_T("String"),
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_CHAR_INDEXABLE
},
{
QSE_T("Link"),
QSE_T("Object"),
QSE_T("link"),
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
},
{
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_NULL,
QSE_STX_SPEC_NOT_INDEXABLE
}
};
qse_word_t 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;
return x;
}
int qse_stx_bootstrap (qse_stx_t* stx)
{
qse_word_t symbol_Smalltalk;
qse_word_t object_meta;
__create_bootstrapping_objects (stx);
/* object, class, and array are precreated for easier instantiation
* of builtin classes */
stx->class_object = qse_stx_new_class (stx, QSE_T("Object"));
stx->class_class = qse_stx_new_class (stx, QSE_T("Class"));
stx->class_array = qse_stx_new_class (stx, QSE_T("Array"));
stx->class_bytearray = qse_stx_new_class (stx, QSE_T("ByteArray"));
stx->class_string = qse_stx_new_class (stx, QSE_T("String"));
stx->class_character = qse_stx_new_class (stx, QSE_T("Character"));
stx->class_context = qse_stx_new_class (stx, QSE_T("Context"));
stx->class_system_dictionary =
qse_stx_new_class (stx, QSE_T("SystemDictionary"));
stx->class_method =
qse_stx_new_class (stx, QSE_T("Method"));
stx->class_smallinteger =
qse_stx_new_class (stx, QSE_T("SmallInteger"));
__create_builtin_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;
/* instance class for Object is set here as it is not
* set in __create_builtin_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 */
QSE_STX_CLASS(stx,stx->smalltalk) = stx->class_system_dictionary;
symbol_Smalltalk = qse_stx_new_symbol (stx, QSE_T("Smalltalk"));
qse_stx_dict_put (stx, stx->smalltalk, symbol_Smalltalk, stx->smalltalk);
/* 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"));
/* nil setClass: UndefinedObject */
QSE_STX_CLASS(stx,stx->nil) =
qse_stx_lookup_class(stx, QSE_T("UndefinedObject"));
/* true setClass: True */
QSE_STX_CLASS(stx,stx->true) =
qse_stx_lookup_class (stx, QSE_T("True"));
/* fales setClass: False */
QSE_STX_CLASS(stx,stx->false) =
qse_stx_lookup_class (stx, QSE_T("False"));
__filein_kernel (stx);
return 0;
}
static void __create_bootstrapping_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;
/* allocate three keyword objects */
stx->nil = qse_stx_alloc_word_object (stx, QSE_NULL, 0, QSE_NULL, 0);
stx->true = qse_stx_alloc_word_object (stx, QSE_NULL, 0, QSE_NULL, 0);
stx->false = qse_stx_alloc_word_object (stx, QSE_NULL, 0, QSE_NULL, 0);
qse_assert (stx->nil == QSE_STX_NIL);
qse_assert (stx->true == QSE_STX_TRUE);
qse_assert (stx->false == QSE_STX_FALSE);
/* system dictionary */
/* TODO: dictionary size */
stx->smalltalk = qse_stx_alloc_word_object (
stx, QSE_NULL, 1, QSE_NULL, 256);
/* set tally */
QSE_STX_WORD_AT(stx,stx->smalltalk,0) = QSE_STX_TO_SMALLINT(0);
/* Symbol */
stx->class_symbol = qse_stx_alloc_word_object(
stx, QSE_NULL, QSE_STX_CLASS_SIZE, QSE_NULL, 0);
/* Metaclass */
stx->class_metaclass = qse_stx_alloc_word_object(
stx, QSE_NULL, QSE_STX_CLASS_SIZE, QSE_NULL, 0);
/* Association */
stx->class_association = qse_stx_alloc_word_object(
stx, QSE_NULL, QSE_STX_CLASS_SIZE, QSE_NULL, 0);
/* Metaclass is a class so it has the same structure
* as a normal class. "Metaclass class" is an instance of
* Metaclass. */
/* Symbol class */
class_SymbolMeta = qse_stx_alloc_word_object(
stx, QSE_NULL, QSE_STX_METACLASS_SIZE, QSE_NULL, 0);
/* Metaclass class */
class_MetaclassMeta = qse_stx_alloc_word_object(
stx, QSE_NULL, QSE_STX_METACLASS_SIZE, QSE_NULL, 0);
/* Association class */
class_AssociationMeta = qse_stx_alloc_word_object(
stx, QSE_NULL, QSE_STX_METACLASS_SIZE, QSE_NULL, 0);
/* (Symbol class) setClass: Metaclass */
QSE_STX_CLASS(stx,class_SymbolMeta) = stx->class_metaclass;
/* (Metaclass class) setClass: Metaclass */
QSE_STX_CLASS(stx,class_MetaclassMeta) = stx->class_metaclass;
/* (Association class) setClass: Metaclass */
QSE_STX_CLASS(stx,class_AssociationMeta) = stx->class_metaclass;
/* Symbol setClass: (Symbol class) */
QSE_STX_CLASS(stx,stx->class_symbol) = class_SymbolMeta;
/* Metaclass setClass: (Metaclass class) */
QSE_STX_CLASS(stx,stx->class_metaclass) = class_MetaclassMeta;
/* Association setClass: (Association class) */
QSE_STX_CLASS(stx,stx->class_association) = class_AssociationMeta;
/* (Symbol class) setSpec: CLASS_SIZE */
QSE_STX_WORD_AT(stx,class_SymbolMeta,QSE_STX_CLASS_SPEC) =
QSE_STX_TO_SMALLINT((QSE_STX_CLASS_SIZE << QSE_STX_SPEC_INDEXABLE_BITS) | QSE_STX_SPEC_NOT_INDEXABLE);
/* (Metaclass class) setSpec: CLASS_SIZE */
QSE_STX_WORD_AT(stx,class_MetaclassMeta,QSE_STX_CLASS_SPEC) =
QSE_STX_TO_SMALLINT((QSE_STX_CLASS_SIZE << QSE_STX_SPEC_INDEXABLE_BITS) | QSE_STX_SPEC_NOT_INDEXABLE);
/* (Association class) setSpec: CLASS_SIZE */
QSE_STX_WORD_AT(stx,class_AssociationMeta,QSE_STX_CLASS_SPEC) =
QSE_STX_TO_SMALLINT((QSE_STX_CLASS_SIZE << QSE_STX_SPEC_INDEXABLE_BITS) | QSE_STX_SPEC_NOT_INDEXABLE);
/* specs for class_metaclass, class_association,
* class_symbol are set later in __create_builtin_classes */
/* #Symbol */
symbol_Symbol = qse_stx_new_symbol (stx, QSE_T("Symbol"));
/* #Metaclass */
symbol_Metaclass = qse_stx_new_symbol (stx, QSE_T("Metaclass"));
/* #Association */
symbol_Association = qse_stx_new_symbol (stx, QSE_T("Association"));
/* Symbol setName: #Symbol */
QSE_STX_WORD_AT(stx,stx->class_symbol,QSE_STX_CLASS_NAME) = symbol_Symbol;
/* Metaclass setName: #Metaclass */
QSE_STX_WORD_AT(stx,stx->class_metaclass,QSE_STX_CLASS_NAME) = symbol_Metaclass;
/* Association setName: #Association */
QSE_STX_WORD_AT(stx,stx->class_association,QSE_STX_CLASS_NAME) = symbol_Association;
/* register class names into the system dictionary */
qse_stx_dict_put (stx,
stx->smalltalk, symbol_Symbol, stx->class_symbol);
qse_stx_dict_put (stx,
stx->smalltalk, symbol_Metaclass, stx->class_metaclass);
qse_stx_dict_put (stx,
stx->smalltalk, symbol_Association, stx->class_association);
}
static void __create_builtin_classes (qse_stx_t* stx)
{
class_info_t* p;
qse_word_t class, superclass, array;
qse_stx_class_t* class_obj, * superclass_obj;
qse_word_t metaclass;
qse_stx_metaclass_t* metaclass_obj;
qse_word_t n, nfields;
qse_assert (stx->class_array != stx->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_new_class (stx, p->name);
}
qse_assert (class != stx->nil);
class_obj = (qse_stx_class_t*)QSE_STX_OBJECT(stx, class);
class_obj->superclass = (p->superclass == QSE_NULL)?
stx->nil: qse_stx_lookup_class(stx,p->superclass);
nfields = 0;
if (p->superclass != QSE_NULL) {
qse_word_t meta;
qse_stx_metaclass_t* meta_obj;
superclass = qse_stx_lookup_class(stx,p->superclass);
qse_assert (superclass != stx->nil);
meta = class_obj->header.class;
meta_obj = (qse_stx_metaclass_t*)QSE_STX_OBJECT(stx,meta);
meta_obj->superclass = QSE_STX_CLASS(stx,superclass);
meta_obj->instance_class = class;
while (superclass != stx->nil) {
superclass_obj = (qse_stx_class_t*)
QSE_STX_OBJECT(stx,superclass);
nfields +=
QSE_STX_FROM_SMALLINT(superclass_obj->spec) >>
QSE_STX_SPEC_INDEXABLE_BITS;
superclass = superclass_obj->superclass;
}
}
if (p->instance_variables != QSE_NULL) {
nfields += __count_names (p->instance_variables);
class_obj->variables =
__new_string (stx, p->instance_variables);
}
qse_assert (nfields <= 0 || (nfields > 0 &&
(p->indexable == QSE_STX_SPEC_NOT_INDEXABLE ||
p->indexable == QSE_STX_SPEC_WORD_INDEXABLE)));
class_obj->spec = QSE_STX_TO_SMALLINT(
(nfields << QSE_STX_SPEC_INDEXABLE_BITS) | p->indexable);
}
for (p = class_info; p->name != QSE_NULL; p++) {
class = qse_stx_lookup_class(stx, p->name);
qse_assert (class != stx->nil);
class_obj = (qse_stx_class_t*)QSE_STX_OBJECT(stx, class);
if (p->class_variables != QSE_NULL) {
class_obj->class_variables =
__make_classvar_dict(stx, class, p->class_variables);
}
/*
TODO:
if (p->pool_dictionaries != QSE_NULL) {
class_obj->pool_dictionaries =
__make_pool_dictionary(stx, class, p->pool_dictionaries);
}
*/
}
/* fill subclasses */
for (p = class_info; p->name != QSE_NULL; p++) {
n = __count_subclasses (p->name);
array = qse_stx_new_array (stx, n);
__set_subclasses (stx, QSE_STX_DATA(stx,array), p->name);
class = qse_stx_lookup_class(stx, p->name);
qse_assert (class != stx->nil);
class_obj = (qse_stx_class_t*)QSE_STX_OBJECT(stx, class);
class_obj->subclasses = array;
}
/* fill subclasses for metaclasses */
for (p = class_info; p->name != QSE_NULL; p++) {
n = __count_subclasses (p->name);
array = qse_stx_new_array (stx, n);
__set_metaclass_subclasses (stx, QSE_STX_DATA(stx,array), p->name);
class = qse_stx_lookup_class(stx, p->name);
qse_assert (class != stx->nil);
metaclass = QSE_STX_CLASS(stx,class);
metaclass_obj = (qse_stx_metaclass_t*)QSE_STX_OBJECT(stx, metaclass);
metaclass_obj->subclasses = array;
}
}
static qse_word_t __count_names (const qse_char_t* str)
{
qse_word_t n = 0;
const qse_char_t* p = str;
do {
while (*p == QSE_T(' ') ||
*p == QSE_T('\t')) p++;
if (*p == QSE_T('\0')) break;
n++;
while (*p != QSE_T(' ') &&
*p != QSE_T('\t') &&
*p != QSE_T('\0')) p++;
} while (1);
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_new_symbolx (stx, name, p - name);
} while (1);
}
static qse_word_t __count_subclasses (const qse_char_t* str)
{
class_info_t* p;
qse_word_t n = 0;
for (p = class_info; p->name != QSE_NULL; p++) {
if (p->superclass == QSE_NULL) continue;
if (qse_strcmp (str, p->superclass) == 0) n++;
}
return n;
}
static void __set_subclasses (
qse_stx_t* stx, qse_word_t* array, const qse_char_t* str)
{
class_info_t* p;
qse_word_t n = 0, class;
for (p = class_info; p->name != QSE_NULL; p++) {
if (p->superclass == QSE_NULL) continue;
if (qse_strcmp (str, p->superclass) != 0) continue;
class = qse_stx_lookup_class (stx, p->name);
qse_assert (class != stx->nil);
array[n++] = class;
}
}
static void __set_metaclass_subclasses (
qse_stx_t* stx, qse_word_t* array, const qse_char_t* str)
{
class_info_t* p;
qse_word_t n = 0, class;
for (p = class_info; p->name != QSE_NULL; p++) {
if (p->superclass == QSE_NULL) continue;
if (qse_strcmp (str, p->superclass) != 0) continue;
class = qse_stx_lookup_class (stx, p->name);
qse_assert (class != stx->nil);
array[n++] = QSE_STX_CLASS(stx,class);
}
}
static qse_word_t __make_classvar_dict (
qse_stx_t* stx, qse_word_t class, const qse_char_t* names)
{
qse_word_t dict, symbol;
const qse_char_t* p = names;
const qse_char_t* name;
dict = qse_stx_instantiate (
stx, stx->class_system_dictionary,
QSE_NULL, QSE_NULL, __count_names(names));
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++;
symbol = qse_stx_new_symbolx (stx, name, p - name);
qse_stx_dict_put (stx, dict, symbol, stx->nil);
} while (1);
return dict;
}
static void __filein_kernel (qse_stx_t* stx)
{
class_info_t* p;
for (p = class_info; p->name != QSE_NULL; p++) {
/* TODO: */
}
}

21
qse/lib/stx/bootstrp.h Normal file
View File

@ -0,0 +1,21 @@
/*
* $Id: bootstrp.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_BOOTSTRP_H_
#define _QSE_STX_BOOTSTRP_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);
int qse_stx_bootstrap (qse_stx_t* stx);
#ifdef __cplusplus
}
#endif
#endif

193
qse/lib/stx/bytecode.c Normal file
View File

@ -0,0 +1,193 @@
/*
* $Id: bytecode.c 118 2008-03-03 11:21:33Z baconevi $
*/
#include <qse/stx/bytecode.h>
#include <qse/stx/class.h>
#include <qse/stx/method.h>
#include <qse/stx/dict.h>
static void __decode1 (qse_stx_t* stx, qse_word_t idx, void* data);
static int __decode2 (qse_stx_t* stx,
qse_stx_class_t* class_obj, qse_stx_method_t* method_obj);
int qse_stx_decode (qse_stx_t* stx, qse_word_t class)
{
qse_stx_class_t* class_obj;
class_obj = (qse_stx_class_t*)QSE_STX_OBJECT(stx, class);
if (class_obj->methods == stx->nil) return 0;
/* TODO */
qse_stx_dict_traverse (stx, class_obj->methods, __decode1, class_obj);
return 0;
}
#include <qse/bas/stdio.h>
static void __dump_object (qse_stx_t* stx, qse_word_t obj)
{
if (QSE_STX_IS_SMALLINT(obj)) {
qse_printf (QSE_T("%d"), QSE_STX_FROM_SMALLINT(obj));
}
else if (QSE_STX_CLASS(stx,obj) == stx->class_character) {
qse_printf (QSE_T("$%c"), QSE_STX_WORD_AT(stx,obj,0));
}
else if (QSE_STX_CLASS(stx,obj) == stx->class_string) {
qse_printf (QSE_T("'%s'"), QSE_STX_DATA(stx,obj));
}
else if (QSE_STX_CLASS(stx,obj) == stx->class_symbol) {
qse_printf (QSE_T("#%s"), QSE_STX_DATA(stx,obj));
}
else if (QSE_STX_IS_CHAR_OBJECT(stx, obj)) {
qse_printf (QSE_T("unknow char object [%s]"), QSE_STX_DATA(stx,obj));
}
else if (QSE_STX_IS_BYTE_OBJECT(stx, obj)) {
qse_printf (QSE_T("unknown byte object"), QSE_STX_DATA(stx,obj));
}
else if (QSE_STX_IS_WORD_OBJECT(stx, obj)) {
qse_printf (QSE_T("unknown word object"), QSE_STX_DATA(stx,obj));
}
else {
qse_printf (QSE_T("invalid object type"));
}
}
static void __decode1 (qse_stx_t* stx, qse_word_t idx, void* data)
{
qse_stx_method_t* method_obj;
qse_stx_class_t* class_obj;
qse_word_t key = QSE_STX_WORD_AT(stx,idx,QSE_STX_ASSOCIATION_KEY);
qse_word_t value = QSE_STX_WORD_AT(stx,idx,QSE_STX_ASSOCIATION_VALUE);
qse_word_t* literals;
qse_word_t literal_count, i;
qse_word_t method_class;
qse_stx_class_t* method_class_obj;
class_obj = (qse_stx_class_t*)data;
qse_printf (QSE_T("* Method: %s\n"), QSE_STX_DATA(stx, key));
method_obj = (qse_stx_method_t*)QSE_STX_OBJECT(stx, value);
literals = method_obj->literals;
/*
literal_count = QSE_STX_SIZE(stx, value) -
(QSE_STX_FROM_SMALLINT(class_obj->spec) >> QSE_STX_SPEC_INDEXABLE_BITS);
*/
method_class = QSE_STX_CLASS(stx,value);
method_class_obj = QSE_STX_OBJECT(stx, method_class);
literal_count = QSE_STX_SIZE(stx,value) -
(QSE_STX_FROM_SMALLINT(method_class_obj->spec) >> QSE_STX_SPEC_INDEXABLE_BITS);
qse_printf (QSE_T("* Literal Count: %d, Temporary Count: %d, Argument Count: %d\n"),
literal_count,
QSE_STX_FROM_SMALLINT(method_obj->tmpcount),
QSE_STX_FROM_SMALLINT(method_obj->argcount));
for (i = 0; i < literal_count; i++) {
qse_printf (QSE_T("%d. ["), i);
__dump_object (stx, literals[i]);
qse_printf (QSE_T("]\n"));
}
__decode2 (stx, data, method_obj);
}
static int __decode2 (qse_stx_t* stx,
qse_stx_class_t* class_obj, qse_stx_method_t* method_obj)
{
qse_stx_byte_object_t* bytecodes;
qse_word_t bytecode_size, pc = 0;
int code, next, next2;
static const qse_char_t* stack_opcode_names[] =
{
QSE_T("push_receiver_variable"),
QSE_T("push_temporary_location"),
QSE_T("push_literal_constant"),
QSE_T("push_literal_variable"),
QSE_T("store_receiver_variable"),
QSE_T("store_temporary_location")
};
static const qse_char_t* send_opcode_names[] =
{
QSE_T("send_to_self"),
QSE_T("send_to_super")
};
static const qse_char_t* stack_special_opcode_names[] =
{
QSE_T("pop_stack_top"),
QSE_T("duplicate_pop_stack_top"),
QSE_T("push_active_context"),
QSE_T("push_nil"),
QSE_T("push_true"),
QSE_T("push_false"),
QSE_T("push_receiver")
};
static const qse_char_t* return_opcode_names[] =
{
QSE_T("return_receiver"),
QSE_T("return_true"),
QSE_T("return_false"),
QSE_T("return_nil"),
QSE_T("return_from_message"),
QSE_T("return_from_block")
};
bytecodes = QSE_STX_BYTE_OBJECT(stx, method_obj->bytecodes);
bytecode_size = QSE_STX_SIZE(stx, method_obj->bytecodes);
while (pc < bytecode_size) {
code = bytecodes->data[pc++];
if (code >= 0x00 && code <= 0x5F) {
/* stack */
qse_printf (QSE_T("%s %d\n"),
stack_opcode_names[code >> 4], code & 0x0F);
}
else if (code >= 0x60 && code <= 0x65) {
/* stack extended */
next = bytecodes->data[pc++];
qse_printf (QSE_T("%s %d\n"),
stack_opcode_names[code & 0x0F], next);
}
else if (code >= 0x67 && code <= 0x6D) {
/* stack special */
qse_printf (QSE_T("%s\n"),
stack_special_opcode_names[code - 0x67]);
}
else if (code >= 0x70 && code <= 0x71 ) {
/* send message */
next = bytecodes->data[pc++];
qse_printf (QSE_T("%s nargs(%d) selector(%d)\n"),
send_opcode_names[code - 0x70], next >> 5, next & 0x1F);
}
else if (code >= 0x72 && code <= 0x73 ) {
/* send message extended */
next = bytecodes->data[pc++];
next2 = bytecodes->data[pc++];
qse_printf (QSE_T("%s %d %d\n"),
send_opcode_names[code - 0x72], next, next2);
}
else if (code >= 0x78 && code <= 0x7D) {
qse_printf (QSE_T("%s\n"),
return_opcode_names[code - 0x78]);
}
else if (code >= 0x80 && code <= 0x8F) {
// jump
}
else if (code >= 0xF0 && code <= 0xFF) {
// primitive
next = bytecodes->data[pc++];
qse_printf (QSE_T("do_primitive %d\n"), ((code & 0x0F) << 8) | next);
}
else {
qse_printf (QSE_T("unknown byte code 0x%x\n"), code);
}
}
return 0;
}

56
qse/lib/stx/bytecode.h Normal file
View File

@ -0,0 +1,56 @@
/*
* $Id: bytecode.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_BYTECODE_H_
#define _QSE_STX_BYTECODE_H_
#include <qse/stx/stx.h>
#define PUSH_RECEIVER_VARIABLE 0x00
#define PUSH_TEMPORARY_LOCATION 0x10
#define PUSH_LITERAL_CONSTANT 0x20
#define PUSH_LITERAL_VARIABLE 0x30
#define STORE_RECEIVER_VARIABLE 0x40
#define STORE_TEMPORARY_LOCATION 0x50
#define PUSH_RECEIVER_VARIABLE_EXTENDED 0x60
#define PUSH_TEMPORARY_LOCATION_EXTENDED 0x61
#define PUSH_LITERAL_CONSTANT_EXTENDED 0x62
#define PUSH_LITERAL_VARIABLE_EXTENDED 0x63
#define STORE_RECEIVER_VARIABLE_EXTENDED 0x64
#define STORE_TEMPORARY_LOCATION_EXTENDED 0x65
#define POP_STACK_TOP 0x67
#define DUPLICATE_POP_STACK_TOP 0x68
#define PUSH_ACTIVE_CONTEXT 0x69
#define PUSH_NIL 0x6A
#define PUSH_TRUE 0x6B
#define PUSH_FALSE 0x6C
#define PUSH_RECEIVER 0x6D
#define SEND_TO_SELF 0x70
#define SEND_TO_SUPER 0x71
#define SEND_TO_SELF_EXTENDED 0x72
#define SEND_TO_SUPER_EXTENDED 0x73
#define RETURN_RECEIVER 0x78
#define RETURN_TRUE 0x79
#define RETURN_FALSE 0x7A
#define RETURN_NIL 0x7B
#define RETURN_FROM_MESSAGE 0x7C
#define RETURN_FROM_BLOCK 0x7D
#define DO_PRIMITIVE 0xF0
#ifdef __cplusplus
extern "C" {
#endif
int qse_stx_decode (qse_stx_t* stx, qse_word_t class_idx);
#ifdef __cplusplus
}
#endif
#endif

168
qse/lib/stx/class.c Normal file
View File

@ -0,0 +1,168 @@
/*
* $Id: class.c 118 2008-03-03 11:21:33Z baconevi $
*/
#include <qse/stx/class.h>
#include <qse/stx/symbol.h>
#include <qse/stx/object.h>
#include <qse/stx/dict.h>
#include <qse/stx/misc.h>
qse_word_t qse_stx_new_class (qse_stx_t* stx, const qse_char_t* name)
{
qse_word_t meta, class;
qse_word_t class_name;
meta = qse_stx_alloc_word_object (
stx, QSE_NULL, QSE_STX_METACLASS_SIZE, QSE_NULL, 0);
QSE_STX_CLASS(stx,meta) = stx->class_metaclass;
/* the spec of the metaclass must be the spec of its
* instance. so the QSE_STX_CLASS_SIZE is set */
QSE_STX_WORD_AT(stx,meta,QSE_STX_METACLASS_SPEC) =
QSE_STX_TO_SMALLINT((QSE_STX_CLASS_SIZE << QSE_STX_SPEC_INDEXABLE_BITS) | QSE_STX_SPEC_NOT_INDEXABLE);
/* the spec of the class is set later in __create_builtin_classes */
class = qse_stx_alloc_word_object (
stx, QSE_NULL, QSE_STX_CLASS_SIZE, QSE_NULL, 0);
QSE_STX_CLASS(stx,class) = meta;
class_name = qse_stx_new_symbol (stx, name);
QSE_STX_WORD_AT(stx,class,QSE_STX_CLASS_NAME) = class_name;
qse_stx_dict_put (stx, stx->smalltalk, class_name, class);
return class;
}
qse_word_t qse_stx_lookup_class (qse_stx_t* stx, const qse_char_t* name)
{
qse_word_t assoc, meta, value;
assoc = qse_stx_dict_lookup (stx, stx->smalltalk, name);
if (assoc == stx->nil) {
return stx->nil;
}
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;
return value;
}
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_OBJECT(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_OBJECT(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_OBJECT(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_OBJECT(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;
}

81
qse/lib/stx/class.h Normal file
View File

@ -0,0 +1,81 @@
/*
* $Id: class.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_CLASS_H_
#define _QSE_STX_CLASS_H_
#include <qse/stx/stx.h>
/* definitions for common objects */
#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 QSE_STX_SPEC_INDEXABLE_BITS 2
#define QSE_STX_SPEC_INDEXABLE_MASK 3
#define QSE_STX_SPEC_NOT_INDEXABLE 0
#define QSE_STX_SPEC_WORD_INDEXABLE 1
#define QSE_STX_SPEC_BYTE_INDEXABLE 2
#define QSE_STX_SPEC_CHAR_INDEXABLE 3
struct qse_stx_class_t
{
qse_stx_objhdr_t header;
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 header;
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;
#ifdef __cplusplus
extern "C" {
#endif
qse_word_t qse_stx_new_class (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);
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);
#ifdef __cplusplus
}
#endif
#endif

75
qse/lib/stx/context.c Normal file
View File

@ -0,0 +1,75 @@
/*
* $Id: context.c 118 2008-03-03 11:21:33Z baconevi $
*/
#include <qse/stx/context.h>
#include <qse/stx/object.h>
#include <qse/stx/class.h>
#include <qse/stx/misc.h>
qse_word_t qse_stx_new_context (qse_stx_t* stx,
qse_word_t method, qse_word_t args, qse_word_t temp)
{
qse_word_t context;
qse_stx_context_t* obj;
context = qse_stx_alloc_word_object(
stx, QSE_NULL, QSE_STX_CONTEXT_SIZE, QSE_NULL, 0);
obj = (qse_stx_context_t*)QSE_STX_OBJECT(stx,context);
obj->header.class = qse_stx_lookup_class(stx,QSE_T("Context"));
obj->ip = QSE_STX_TO_SMALLINT(0);
obj->method = method;
obj->arguments = args;
obj->temporaries = temp;
return context;
}
static qse_byte_t __fetch_byte (
qse_stx_t* stx, qse_stx_context_t* context_obj)
{
qse_word_t ip, method;
qse_assert (QSE_STX_IS_SMALLINT(context_obj->ip));
ip = QSE_STX_FROM_SMALLINT(context_obj->ip);
method = context_obj->method;
/* increment instruction pointer */
context_obj->ip = QSE_STX_TO_SMALLINT(ip + 1);
qse_assert (QSE_STX_TYPE(stx,method) == QSE_STX_BYTE_INDEXED);
return QSE_STX_BYTE_AT(stx,method,ip);
}
int qse_stx_run_context (qse_stx_t* stx, qse_word_t context)
{
qse_byte_t byte, operand;
qse_stx_context_t* context_obj;
context_obj = (qse_stx_context_t*)QSE_STX_OBJECT(stx,context);
while (!stx->__wantabort) {
/* check_process_switch (); // hopefully */
byte = __fetch_byte (stx, context_obj);
#ifdef _DOS
printf (QSE_T("code: %x\n"), byte);
#else
qse_printf (QSE_T("code: %x\n"), byte);
#endif
switch (byte) {
case PUSH_OBJECT:
operand = __fetch_byte (stx, context_obj);
break;
case SEND_UNARY_MESSAGE:
operand = __fetch_byte (stx, context_obj);
break;
case HALT:
goto exit_run_context;
}
}
exit_run_context:
return 0;
}

43
qse/lib/stx/context.h Normal file
View File

@ -0,0 +1,43 @@
/*
* $Id: context.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_CONTEXT_H_
#define _QSE_STX_CONTEXT_H_
#include <qse/stx/stx.h>
#define PUSH_OBJECT 0xA0
#define SEND_UNARY_MESSAGE 0xB0
#define HALT 0xFF
#define QSE_STX_CONTEXT_SIZE 4
#define QSE_STX_CONTEXT_IP 0
#define QSE_STX_CONTEXT_METHOD 1
#define QSE_STX_CONTEXT_ARGUMENTS 2
#define QSE_STX_CONTEXT_TEMPORARIES 3
struct qse_stx_context_t
{
qse_stx_objhdr_t header;
qse_word_t ip;
qse_word_t method;
qse_word_t arguments;
qse_word_t temporaries;
};
typedef struct qse_stx_context_t qse_stx_context_t;
#ifdef __cplusplus
extern "C" {
#endif
qse_word_t qse_stx_new_context (qse_stx_t* stx,
qse_word_t method, qse_word_t args, qse_word_t temp);
int qse_stx_run_context (qse_stx_t* stx, qse_word_t context);
#ifdef __cplusplus
}
#endif
#endif

190
qse/lib/stx/dict.c Normal file
View File

@ -0,0 +1,190 @@
/*
* $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;
#ifdef __GNUC__
qse_word_t data[2] = { key, value };
#else
qse_word_t data[2];
data[0] = key;
data[1] = value;
#endif
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_IS_SMALLINT(dict) &&
QSE_STX_IS_WORD_OBJECT(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_OBJECT(stx,dict),
QSE_STX_OBJECT(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_IS_SMALLINT(dict) &&
QSE_STX_IS_WORD_OBJECT(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_FROM_SMALLINT(QSE_STX_WORD_AT(stx,dict,0));
if (capa <= tally + 1) {
__grow_dict (stx, dict);
/* refresh tally */
tally = QSE_STX_FROM_SMALLINT(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);
}
}

42
qse/lib/stx/dict.h Normal file
View File

@ -0,0 +1,42 @@
/*
* $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

380
qse/lib/stx/interp.c Normal file
View File

@ -0,0 +1,380 @@
/*
* $Id: interp.c 118 2008-03-03 11:21:33Z baconevi $
*/
#include <qse/stx/interp.h>
#include <qse/stx/method.h>
#include <qse/stx/object.h>
#include <qse/stx/array.h>
#include <qse/stx/class.h>
#include <qse/bas/assert.h>
#include <qse/bas/memory.h>
/*
activation record
....
....
....
-------------------
previous stack_base
-------------------
method
-------------------
pc
-------------------
temporaries
-------------------
arguments
-------------------
receiver
------------------- <----- current stack_base
....
....
....
*/
struct process_t
{
qse_word_t* stack;
qse_word_t stack_size;
qse_word_t stack_base;
qse_word_t stack_top;
qse_word_t receiver;
qse_word_t method;
qse_word_t pc;
/* cached information about the method above */
qse_word_t* literals;
qse_byte_t* bytecodes;
qse_word_t bytecode_size;
qse_size_t argcount;
qse_size_t tmpcount;
};
typedef struct process_t process_t;
static int __run_process (qse_stx_t* stx, process_t* proc);
static int __push_to_stack (qse_stx_t* stx,
process_t* proc, qse_word_t what, qse_word_t index);
static int __store_from_stack (qse_stx_t* stx,
process_t* proc, qse_word_t what, qse_word_t index);
static int __send_message (qse_stx_t* stx, process_t* proc,
qse_word_t nargs, qse_word_t selector, qse_bool_t to_super);
static int __return_from_message (qse_stx_t* stx, process_t* proc);
static int __dispatch_primitive (qse_stx_t* stx, process_t* proc, qse_word_t no);
int qse_stx_interp (qse_stx_t* stx, qse_word_t receiver, qse_word_t method)
{
process_t proc;
qse_stx_method_t* mthobj;
qse_word_t i;
int n;
// TODO: size of process stack.
proc.stack = (qse_word_t*)qse_malloc (10000 * qse_sizeof(qse_word_t));
if (proc.stack == QSE_NULL) {
qse_printf (QSE_T("out of memory in qse_stx_interp\n"));
return -1;
}
proc.stack_size = 10000;
proc.stack_base = 0;
proc.stack_top = 0;
mthobj = (qse_stx_method_t*)QSE_STX_OBJECT(stx,method);
qse_assert (mthobj != QSE_NULL);
proc.literals = mthobj->literals;
proc.bytecodes = QSE_STX_DATA(stx, mthobj->bytecodes);
proc.bytecode_size = QSE_STX_SIZE(stx, mthobj->bytecodes);
/* TODO: disable the method with arguments for start-up */
proc.argcount = QSE_STX_FROM_SMALLINT(mthobj->argcount);
proc.tmpcount = QSE_STX_FROM_SMALLINT(mthobj->tmpcount);
proc.receiver = receiver;
proc.method = method;
proc.pc = 0;
proc.stack_base = proc.stack_top;
/* push the receiver */
proc.stack[proc.stack_top++] = receiver;
/* push arguments */
for (i = 0; i < proc.argcount; i++) {
proc.stack[proc.stack_top++] = stx->nil;
}
/* secure space for temporaries */
for (i = 0; i < proc.tmpcount; i++)
proc.stack[proc.stack_top++] = stx->nil;
/* push dummy pc */
proc.stack[proc.stack_top++] = 0;
/* push dummy method */
proc.stack[proc.stack_top++] = stx->nil;
/* push dummy previous stack base */
proc.stack[proc.stack_top++] = 0;
n = __run_process (stx, &proc);
qse_free (proc.stack);
return n;
}
static int __run_process (qse_stx_t* stx, process_t* proc)
{
int code, next, next2;
while (proc->pc < proc->bytecode_size) {
code = proc->bytecodes[proc->pc++];
#ifdef DEBUG
qse_printf (QSE_T("code = 0x%x\n"), code);
#endif
if (code >= 0x00 && code <= 0x3F) {
/* stack - push */
__push_to_stack (stx, proc, code >> 4, code & 0x0F);
}
else if (code >= 0x40 && code <= 0x5F) {
/* stack - store */
int what = code >> 4;
int index = code & 0x0F;
__store_from_stack (stx, proc, code >> 4, code & 0x0F);
}
/* TODO: more here .... */
else if (code == 0x67) {
/* pop stack top */
proc->stack_top--;
}
/* TODO: more here .... */
else if (code == 0x6A) {
proc->stack[proc->stack_top++] = stx->nil;
}
else if (code == 0x6B) {
proc->stack[proc->stack_top++] = stx->true;
}
else if (code == 0x6C) {
proc->stack[proc->stack_top++] = stx->false;
}
else if (code == 0x6D) {
/* push receiver */
proc->stack[proc->stack_top++] = proc->receiver;
}
/* TODO: more here .... */
else if (code == 0x70) {
/* send message to self */
next = proc->bytecodes[proc->pc++];
if (__send_message (stx, proc, next >> 5,
proc->literals[next & 0x1F], qse_false) == -1) break;
}
else if (code == 0x71) {
/* send message to super */
next = proc->bytecodes[proc->pc++];
if (__send_message (stx, proc, next >> 5,
proc->literals[next & 0x1F], qse_true) == -1) break;
}
else if (code == 0x72) {
/* send message to self extended */
next = proc->bytecodes[proc->pc++];
next2 = proc->bytecodes[proc->pc++];
if (__send_message (stx, proc, next >> 5,
proc->literals[next2], qse_false) == -1) break;
}
else if (code == 0x73) {
/* send message to super extended */
next = proc->bytecodes[proc->pc++];
next2 = proc->bytecodes[proc->pc++];
if (__send_message (stx, proc, next >> 5,
proc->literals[next2], qse_true) == -1) break;
}
/* more code .... */
else if (code == 0x78) {
/* return receiver */
proc->stack[proc->stack_top++] = proc->receiver;
if (__return_from_message (stx, proc) == -1) break;
}
else if (code == 0x7C) {
/* return from message */
if (__return_from_message (stx, proc) == -1) break;
}
else if (code >= 0xF0 && code <= 0xFF) {
/* primitive */
next = proc->bytecodes[proc->pc++];
__dispatch_primitive (stx, proc, ((code & 0x0F) << 8) | next);
}
else {
qse_printf (QSE_T("INVALID OPCODE...........\n"));
break;
}
}
return 0;
}
static int __push_to_stack (qse_stx_t* stx,
process_t* proc, qse_word_t what, qse_word_t index)
{
switch (what) {
case 0: /* receiver variable */
proc->stack[proc->stack_top++] =
QSE_STX_WORD_AT(stx, proc->stack[proc->stack_base], index);
break;
case 1: /* temporary variable */
proc->stack[proc->stack_top++] =
proc->stack[proc->stack_base + 1 + index];
break;
case 2: /* literal constant */
proc->stack[proc->stack_top++] = proc->literals[index];
break;
case 3: /* literal variable */
break;
}
return 0;
}
static int __store_from_stack (qse_stx_t* stx,
process_t* proc, qse_word_t what, qse_word_t index)
{
switch (what) {
case 4: /* receiver variable */
QSE_STX_WORD_AT(stx,proc->stack[proc->stack_base],index) = proc->stack[--proc->stack_top];
break;
case 5: /* temporary location */
proc->stack[proc->stack_base + 1 + index] = proc->stack[--proc->stack_top];
break;
}
return 0;
}
static int __send_message (qse_stx_t* stx, process_t* proc,
qse_word_t nargs, qse_word_t selector, qse_bool_t to_super)
{
qse_word_t receiver, method;
qse_word_t i, tmpcount, argcount;
qse_stx_method_t* mthobj;
qse_assert (QSE_STX_CLASS(stx,selector) == stx->class_symbol);
receiver = proc->stack[proc->stack_top - nargs - 1];
method = qse_stx_lookup_method (
stx, QSE_STX_CLASS(stx,receiver),
QSE_STX_DATA(stx,selector), to_super);
if (method == stx->nil) {
qse_printf (QSE_T("cannot find the method....\n"));
return -1;
}
mthobj = (qse_stx_method_t*)QSE_STX_OBJECT(stx,method);
argcount = QSE_STX_FROM_SMALLINT(mthobj->argcount);
tmpcount = QSE_STX_FROM_SMALLINT(mthobj->tmpcount);
qse_assert (argcount == nargs);
/* secure space for temporaries */
for (i = 0; i < tmpcount; i++) {
proc->stack[proc->stack_top++] = stx->nil;
}
/* push pc */
proc->stack[proc->stack_top++] = proc->pc;
/* push method */
proc->stack[proc->stack_top++] = proc->method;
/* push previous stack base */
proc->stack[proc->stack_top++] = proc->stack_base;
proc->stack_base = proc->stack_top - 3 - tmpcount - argcount - 1;
qse_assert (proc->stack_base > 0);
proc->receiver = receiver;
proc->method = method;
proc->pc = 0;
proc->literals = mthobj->literals;
proc->bytecodes = QSE_STX_DATA(stx, mthobj->bytecodes);
proc->bytecode_size = QSE_STX_SIZE(stx, mthobj->bytecodes);
proc->argcount = argcount;
proc->tmpcount = tmpcount;
return 0;
}
static int __return_from_message (qse_stx_t* stx, process_t* proc)
{
qse_word_t method, pc, stack_base;
qse_stx_method_t* mthobj;
if (proc->stack_base == 0) {
/* return from the startup method */
return -1;
}
stack_base = proc->stack[proc->stack_base + 1 + proc->tmpcount + proc->argcount + 2];
method = proc->stack[proc->stack_base + 1 + proc->tmpcount + proc->argcount + 1];
pc = proc->stack[proc->stack_base + 1 + proc->tmpcount + proc->argcount];
mthobj = (qse_stx_method_t*)QSE_STX_OBJECT(stx,method);
qse_assert (mthobj != QSE_NULL);
/* return value is located on top of the previous stack */
proc->stack[proc->stack_base - 1] = proc->stack[proc->stack_top - 1];
/* restore the stack pointers */
proc->stack_top = proc->stack_base;
proc->stack_base = stack_base;
proc->receiver = proc->stack[stack_base];
proc->method = method;
proc->pc = pc;
proc->literals = mthobj->literals;
proc->bytecodes = QSE_STX_DATA(stx, mthobj->bytecodes);
proc->bytecode_size = QSE_STX_SIZE(stx, mthobj->bytecodes);
proc->argcount = QSE_STX_FROM_SMALLINT(mthobj->argcount);
proc->tmpcount = QSE_STX_FROM_SMALLINT(mthobj->tmpcount);
return 0;
}
static int __dispatch_primitive (qse_stx_t* stx, process_t* proc, qse_word_t no)
{
switch (no) {
case 0:
qse_printf (QSE_T("[[ hello stx smalltalk ]]\n"));
break;
case 1:
qse_printf (QSE_T("<< AMAZING STX SMALLTALK WORLD >>\n"));
break;
case 2:
qse_printf (QSE_T("<< FUNKY STX SMALLTALK >> %d\n"),
QSE_STX_FROM_SMALLINT(proc->stack[proc->stack_base + 1]));
break;
case 3:
qse_printf (QSE_T("<< HIGH STX SMALLTALK >> %d, %d\n"),
QSE_STX_FROM_SMALLINT(proc->stack[proc->stack_base + 1]),
QSE_STX_FROM_SMALLINT(proc->stack[proc->stack_base + 2]));
break;
case 20:
qse_printf (QSE_T("<< PRIMITIVE 20 >>\n"));
break;
}
return 0;
}

20
qse/lib/stx/interp.h Normal file
View File

@ -0,0 +1,20 @@
/*
* $Id: interp.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_INTERP_H_
#define _QSE_STX_INTERP_H_
#include <qse/stx/stx.h>
#ifdef __cplusplus
extern "C" {
#endif
int qse_stx_interp (qse_stx_t* stx, qse_word_t receiver, qse_word_t method);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,31 @@
!Object methods!
= aValue
^ self == aValue
!
== aValue
^ <21 self aValue>
!
basicAt: index
^<25 self index>
!
basicAt: index put: value
^<31 self index value>
!
basicSize
^<12 self>
!
isNil
^false.
!
notNil
^false.
!!

117
qse/lib/stx/makefile.in Normal file
View File

@ -0,0 +1,117 @@
#
# $Id: makefile.in,v 1.4 2007/09/11 13:42:54 bacon Exp $
#
NAME = asestx
TOP_BUILDDIR = @abs_top_builddir@
TOP_INSTALLDIR = @prefix@/ase
CC = @CC@
CXX = @CXX@
AR = @AR@
RANLIB = @RANLIB@
CFLAGS = @CFLAGS@ -I@abs_top_builddir@/..
CXXFLAGS = @CXXFLAGS@ -I@abs_top_builddir@/..
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
MODE = @BUILDMODE@
JAVAC = @JAVAC@
JAR = @JAR@
CFLAGS_JNI = @CFLAGS_JNI@
JNI = @JNI@
LIBTOOL_COMPILE = ../libtool --mode=compile
LIBTOOL_LINK = ../libtool --mode=link
OUT_DIR = ../$(MODE)/lib
OUT_FILE_LIB = $(OUT_DIR)/lib$(NAME).a
OUT_FILE_JNI = $(OUT_DIR)/lib$(NAME)_jni.la
OUT_FILE_LIB_CXX = $(OUT_DIR)/lib$(NAME)++.a
OUT_FILE_JAR = $(OUT_DIR)/$(NAME).jar
TMP_DIR = $(MODE)
TMP_DIR_CXX = $(TMP_DIR)/cxx
OBJ_FILES_LIB = \
$(TMP_DIR)/stx.o \
$(TMP_DIR)/memory.o \
$(TMP_DIR)/object.o \
$(TMP_DIR)/symbol.o \
$(TMP_DIR)/class.o \
$(TMP_DIR)/array.o \
$(TMP_DIR)/dict.o \
$(TMP_DIR)/misc.o \
$(TMP_DIR)/context.o \
$(TMP_DIR)/name.o \
$(TMP_DIR)/token.o \
$(TMP_DIR)/parser.o \
$(TMP_DIR)/bootstrp.o \
$(TMP_DIR)/bytecode.o \
$(TMP_DIR)/interp.o
OBJ_FILES_SO = $(OBJ_FILES_LIB:.o=.lo)
lib: build
build: $(OUT_FILE_LIB)
$(OUT_FILE_LIB): $(TMP_DIR) $(OUT_DIR) $(OBJ_FILES_LIB)
$(AR) cr $(OUT_FILE_LIB) $(OBJ_FILES_LIB)
if [ ! -z "$(RANLIB)" ]; then $(RANLIB) $(OUT_FILE_LIB); fi
$(TMP_DIR)/stx.o: stx.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c stx.c
$(TMP_DIR)/memory.o: memory.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c memory.c
$(TMP_DIR)/object.o: object.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c object.c
$(TMP_DIR)/symbol.o: symbol.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c symbol.c
$(TMP_DIR)/class.o: class.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c class.c
$(TMP_DIR)/array.o: array.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c array.c
$(TMP_DIR)/dict.o: dict.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c dict.c
$(TMP_DIR)/misc.o: misc.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c misc.c
$(TMP_DIR)/context.o: context.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c context.c
$(TMP_DIR)/name.o: name.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c name.c
$(TMP_DIR)/token.o: token.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c token.c
$(TMP_DIR)/parser.o: parser.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c parser.c
$(TMP_DIR)/bootstrp.o: bootstrp.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c bootstrp.c
$(TMP_DIR)/bytecode.o: bytecode.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c bytecode.c
$(TMP_DIR)/interp.o: interp.c
$(LIBTOOL_COMPILE) $(CC) $(CFLAGS) -o $@ -c interp.c
$(OUT_DIR):
mkdir -p $(OUT_DIR)
$(TMP_DIR):
mkdir -p $(TMP_DIR)
clean:
rm -rf $(OUT_FILE_LIB) $(OBJ_FILES_LIB)

98
qse/lib/stx/memory.c Normal file
View File

@ -0,0 +1,98 @@
/*
* $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];
}

26
qse/lib/stx/memory.h Normal file
View File

@ -0,0 +1,26 @@
/*
* $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_memory_open (
qse_stx_memory_t* mem, qse_word_t capacity);
void qse_stx_memory_close (qse_stx_memory_t* mem);
void qse_stx_memory_gc (qse_stx_memory_t* mem);
qse_word_t qse_stx_memory_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

50
qse/lib/stx/method.h Normal file
View File

@ -0,0 +1,50 @@
/*
* $Id: method.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_METHOD_H_
#define _QSE_STX_METHOD_H_
#include <qse/stx/stx.h>
#define QSE_STX_METHOD_SIZE 5
#define QSE_STX_METHOD_TEXT 0
#define QSE_STX_METHOD_SELECTOR 1
#define QSE_STX_METHOD_BYTECODES 2
#define QSE_STX_METHOD_TMPCOUNT 3
#define QSE_STX_METHOD_ARGCOUNT 4
/* dolphin smalltalk's flags representation
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
-------------------------------------------------------------------------------------------------
| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 1| | | | 0| 0| 0| 1|
-------------------------------------------------------------------------------------------------
\----------|-----------/ \----------|----------/ \---------|-----------/ | \---|--/ |
extraIndex arg Count temp Count | flags |
| |
Block flag SmallInteger flag"
*/
struct qse_stx_method_t
{
qse_stx_objhdr_t header;
qse_word_t text;
qse_word_t selector; /* is this necessary? */
qse_word_t bytecodes;
qse_word_t tmpcount;
qse_word_t argcount;
qse_word_t literals[1];
};
typedef struct qse_stx_method_t qse_stx_method_t;
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

70
qse/lib/stx/misc.c Normal file
View File

@ -0,0 +1,70 @@
/*
* $Id: misc.c 118 2008-03-03 11:21:33Z baconevi $
*/
#include <qse/stx/misc.h>
qse_word_t qse_stx_hash (const void* data, qse_word_t len)
{
qse_word_t h = 0;
qse_byte_t* bp, * be;
bp = (qse_byte_t*)data; be = bp + len;
while (bp < be) h = h * 31 + *bp++;
return h;
}
qse_word_t qse_stx_strhash (const qse_char_t* str)
{
qse_word_t h = 0;
qse_byte_t* bp, * be;
const qse_char_t* p = str;
while (*p != QSE_T('\0')) {
bp = (qse_byte_t*)p;
be = bp + qse_sizeof(qse_char_t);
while (bp < be) h = h * 31 + *bp++;
p++;
}
return h;
}
qse_word_t qse_stx_strxhash (const qse_char_t* str, qse_word_t len)
{
qse_word_t h = 0;
qse_byte_t* bp, * be;
const qse_char_t* p = str, * end = str + len;
while (p < end) {
bp = (qse_byte_t*)p;
be = bp + qse_sizeof(qse_char_t);
while (bp < be) h = h * 31 + *bp++;
p++;
}
return h;
}
qse_char_t* qse_stx_strword (
const qse_char_t* str, const qse_char_t* word, qse_word_t* word_index)
{
qse_char_t* p = (qse_char_t*)str;
qse_char_t* tok;
qse_size_t len;
qse_word_t index = 0;
while (p != QSE_NULL) {
p = qse_strtok (p, QSE_T(""), &tok, &len);
if (qse_strxcmp (tok, len, word) == 0) {
*word_index = index;
return tok;
}
index++;
}
*word_index = index;
return QSE_NULL;
}

63
qse/lib/stx/misc.h Normal file
View File

@ -0,0 +1,63 @@
/*
* $Id: misc.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_MISC_H_
#define _QSE_STX_MISC_H_
#include <qse/stx/stx.h>
/* TODO: remove this header later */
#include <qse/bas/stdio.h>
#ifdef _DOS
#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define qse_assert assert
#define qse_malloc malloc
#define qse_realloc realloc
#define qse_free free
#define qse_va_list va_list
#define qse_va_start va_start
#define qse_va_end va_end
#define qse_va_arg va_arg
#define qse_isspace isspace
#define qse_isdigit isdigit
#define qse_isalpha isalpha
#define qse_isalnum isalnum
#else
#include <qse/bas/memory.h>
#include <qse/bas/assert.h>
#include <qse/bas/stdarg.h>
#include <qse/bas/ctype.h>
#include <qse/bas/string.h>
#include <qse/bas/stdlib.h>
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
#define INLINE
#else
#define INLINE inline
#endif
#ifdef __cplusplus
extern "C" {
#endif
qse_word_t qse_stx_hash (const void* data, qse_word_t len);
qse_word_t qse_stx_strhash (const qse_char_t* str);
qse_word_t qse_stx_strxhash (const qse_char_t* str, qse_word_t len);
qse_char_t* qse_stx_strword (
const qse_char_t* str, const qse_char_t* word, qse_word_t* word_index);
#ifdef __cplusplus
}
#endif
#endif

146
qse/lib/stx/name.c Normal file
View File

@ -0,0 +1,146 @@
/*
* $Id: name.c 118 2008-03-03 11:21:33Z baconevi $
*/
#include <qse/stx/name.h>
#include <qse/stx/misc.h>
qse_stx_name_t* qse_stx_name_open (
qse_stx_name_t* name, qse_word_t capacity)
{
if (capacity == 0)
capacity = qse_countof(name->static_buffer) - 1;
if (name == QSE_NULL) {
name = (qse_stx_name_t*)
qse_malloc (qse_sizeof(qse_stx_name_t));
if (name == QSE_NULL) return QSE_NULL;
name->__dynamic = qse_true;
}
else name->__dynamic = qse_false;
if (capacity < qse_countof(name->static_buffer)) {
name->buffer = name->static_buffer;
}
else {
name->buffer = (qse_char_t*)
qse_malloc ((capacity + 1) * qse_sizeof(qse_char_t));
if (name->buffer == QSE_NULL) {
if (name->__dynamic) qse_free (name);
return QSE_NULL;
}
}
name->size = 0;
name->capacity = capacity;
name->buffer[0] = QSE_T('\0');
return name;
}
void qse_stx_name_close (qse_stx_name_t* name)
{
if (name->capacity >= qse_countof(name->static_buffer)) {
qse_assert (name->buffer != name->static_buffer);
qse_free (name->buffer);
}
if (name->__dynamic) qse_free (name);
}
int qse_stx_name_addc (qse_stx_name_t* name, qse_cint_t c)
{
if (name->size >= name->capacity) {
/* double the capacity. */
qse_size_t new_capacity = name->capacity * 2;
if (new_capacity >= qse_countof(name->static_buffer)) {
qse_char_t* space;
if (name->capacity < qse_countof(name->static_buffer)) {
space = (qse_char_t*)qse_malloc (
(new_capacity + 1) * qse_sizeof(qse_char_t));
if (space == QSE_NULL) return -1;
/* don't need to copy up to the terminating null */
qse_memcpy (space, name->buffer,
name->capacity * qse_sizeof(qse_char_t));
}
else {
space = (qse_char_t*)qse_realloc (name->buffer,
(new_capacity + 1) * qse_sizeof(qse_char_t));
if (space == QSE_NULL) return -1;
}
name->buffer = space;
}
name->capacity = new_capacity;
}
name->buffer[name->size++] = c;
name->buffer[name->size] = QSE_T('\0');
return 0;
}
int qse_stx_name_adds (qse_stx_name_t* name, const qse_char_t* s)
{
while (*s != QSE_T('\0')) {
if (qse_stx_name_addc(name, *s) == -1) return -1;
s++;
}
return 0;
}
void qse_stx_name_clear (qse_stx_name_t* name)
{
name->size = 0;
name->buffer[0] = QSE_T('\0');
}
qse_char_t* qse_stx_name_yield (qse_stx_name_t* name, qse_word_t capacity)
{
qse_char_t* old_buffer, * new_buffer;
if (capacity == 0)
capacity = qse_countof(name->static_buffer) - 1;
if (name->capacity < qse_countof(name->static_buffer)) {
old_buffer = (qse_char_t*)
qse_malloc((name->capacity + 1) * qse_sizeof(qse_char_t));
if (old_buffer == QSE_NULL) return QSE_NULL;
qse_memcpy (old_buffer, name->buffer,
(name->capacity + 1) * qse_sizeof(qse_char_t));
}
else old_buffer = name->buffer;
if (capacity < qse_countof(name->static_buffer)) {
new_buffer = name->static_buffer;
}
else {
new_buffer = (qse_char_t*)
qse_malloc((capacity + 1) * qse_sizeof(qse_char_t));
if (new_buffer == QSE_NULL) return QSE_NULL;
}
name->buffer = new_buffer;
name->size = 0;
name->capacity = capacity;
name->buffer[0] = QSE_T('\0');
return old_buffer;
}
int qse_stx_name_compare (qse_stx_name_t* name, const qse_char_t* str)
{
qse_char_t* p = name->buffer;
qse_word_t index = 0;
while (index < name->size) {
if (*p > *str) return 1;
if (*p < *str) return -1;
index++; p++; str++;
}
return (*str == QSE_T('\0'))? 0: -1;
}

39
qse/lib/stx/name.h Normal file
View File

@ -0,0 +1,39 @@
/*
* $Id: name.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_NAME_H_
#define _QSE_STX_NAME_H_
#include <qse/stx/stx.h>
struct qse_stx_name_t
{
qse_word_t capacity;
qse_word_t size;
qse_char_t* buffer;
qse_char_t static_buffer[128];
qse_bool_t __dynamic;
};
typedef struct qse_stx_name_t qse_stx_name_t;
#ifdef __cplusplus
extern "C" {
#endif
qse_stx_name_t* qse_stx_name_open (
qse_stx_name_t* name, qse_word_t capacity);
void qse_stx_name_close (qse_stx_name_t* name);
int qse_stx_name_addc (qse_stx_name_t* name, qse_cint_t c);
int qse_stx_name_adds (qse_stx_name_t* name, const qse_char_t* s);
void qse_stx_name_clear (qse_stx_name_t* name);
qse_char_t* qse_stx_name_yield (qse_stx_name_t* name, qse_word_t capacity);
int qse_stx_name_compare (qse_stx_name_t* name, const qse_char_t* str);
#ifdef __cplusplus
}
#endif
#endif

246
qse/lib/stx/object.c Normal file
View File

@ -0,0 +1,246 @@
/*
* $Id: object.c 118 2008-03-03 11:21:33Z baconevi $
*/
#include <qse/stx/object.h>
#include <qse/stx/memory.h>
#include <qse/stx/symbol.h>
#include <qse/stx/class.h>
#include <qse/stx/misc.h>
/* n: number of instance variables */
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 idx, n;
qse_stx_word_object_t* obj;
qse_assert (stx->nil == QSE_STX_NIL);
/* bytes to allocated =
* (number of instance variables +
* number of variable instance variables) * word_size
*/
n = nfields + variable_nfields;
idx = qse_stx_memory_alloc (&stx->memory,
n * qse_sizeof(qse_word_t) + qse_sizeof(qse_stx_object_t));
if (idx >= stx->memory.capacity) return idx; /* failed TODO: return a difference value OINDEX_INVALID */
idx = QSE_STX_TO_OINDEX(idx);
obj = QSE_STX_WORD_OBJECT(stx,idx);
obj->header.class = stx->nil;
obj->header.access = (n << 2) | QSE_STX_WORD_INDEXED;
if (variable_data == QSE_NULL) {
while (n > nfields) obj->data[--n] = stx->nil;
}
else {
while (n > nfields) {
n--; obj->data[n] = variable_data[n - nfields];
}
}
if (data == QSE_NULL) {
while (n > 0) obj->data[--n] = stx->nil;
}
else {
while (n > 0) {
n--; obj->data[n] = data[n];
}
}
return idx;
}
/* n: number of bytes */
qse_word_t qse_stx_alloc_byte_object (
qse_stx_t* stx, const qse_byte_t* data, qse_word_t n)
{
qse_word_t idx;
qse_stx_byte_object_t* obj;
qse_assert (stx->nil == QSE_STX_NIL);
idx = qse_stx_memory_alloc (
&stx->memory, n + qse_sizeof(qse_stx_object_t));
if (idx >= stx->memory.capacity) return idx; /* failed */
idx = QSE_STX_TO_OINDEX(idx);
obj = QSE_STX_BYTE_OBJECT(stx,idx);
obj->header.class = stx->nil;
obj->header.access = (n << 2) | QSE_STX_BYTE_INDEXED;
if (data == QSE_NULL) {
while (n-- > 0) obj->data[n] = 0;
}
else {
while (n-- > 0) obj->data[n] = data[n];
}
return idx;
}
qse_word_t qse_stx_alloc_char_object (
qse_stx_t* stx, const qse_char_t* str)
{
return (str == QSE_NULL)?
qse_stx_alloc_char_objectx (stx, QSE_NULL, 0):
qse_stx_alloc_char_objectx (stx, str, qse_strlen(str));
}
/* n: number of characters */
qse_word_t qse_stx_alloc_char_objectx (
qse_stx_t* stx, const qse_char_t* str, qse_word_t n)
{
qse_word_t idx;
qse_stx_char_object_t* obj;
qse_assert (stx->nil == QSE_STX_NIL);
idx = qse_stx_memory_alloc (&stx->memory,
(n + 1) * qse_sizeof(qse_char_t) + qse_sizeof(qse_stx_object_t));
if (idx >= stx->memory.capacity) return idx; /* failed */
idx = QSE_STX_TO_OINDEX(idx);
obj = QSE_STX_CHAR_OBJECT(stx,idx);
obj->header.class = stx->nil;
obj->header.access = (n << 2) | QSE_STX_CHAR_INDEXED;
obj->data[n] = QSE_T('\0');
if (str == QSE_NULL) {
while (n-- > 0) obj->data[n] = QSE_T('\0');
}
else {
while (n-- > 0) obj->data[n] = str[n];
}
return idx;
}
qse_word_t qse_stx_allocn_char_object (qse_stx_t* stx, ...)
{
qse_word_t idx, n = 0;
const qse_char_t* p;
qse_va_list ap;
qse_stx_char_object_t* obj;
qse_assert (stx->nil == QSE_STX_NIL);
qse_va_start (ap, stx);
while ((p = qse_va_arg(ap, const qse_char_t*)) != QSE_NULL) {
n += qse_strlen(p);
}
qse_va_end (ap);
idx = qse_stx_memory_alloc (&stx->memory,
(n + 1) * qse_sizeof(qse_char_t) + qse_sizeof(qse_stx_object_t));
if (idx >= stx->memory.capacity) return idx; /* failed */
idx = QSE_STX_TO_OINDEX(idx);
obj = QSE_STX_CHAR_OBJECT(stx,idx);
obj->header.class = stx->nil;
obj->header.access = (n << 2) | QSE_STX_CHAR_INDEXED;
obj->data[n] = QSE_T('\0');
qse_va_start (ap, stx);
n = 0;
while ((p = qse_va_arg(ap, const qse_char_t*)) != QSE_NULL) {
while (*p != QSE_T('\0')) {
/*QSE_STX_CHAR_AT(stx,idx,n++) = *p++;*/
obj->data[n++] = *p++;
}
}
qse_va_end (ap);
return idx;
}
qse_word_t qse_stx_hash_object (qse_stx_t* stx, qse_word_t object)
{
qse_word_t hv;
if (QSE_STX_IS_SMALLINT(object)) {
qse_word_t tmp = QSE_STX_FROM_SMALLINT(object);
hv = qse_stx_hash(&tmp, qse_sizeof(tmp));
}
else if (QSE_STX_IS_CHAR_OBJECT(stx,object)) {
/* the additional null is not taken into account */
hv = qse_stx_hash (QSE_STX_DATA(stx,object),
QSE_STX_SIZE(stx,object) * qse_sizeof(qse_char_t));
}
else if (QSE_STX_IS_BYTE_OBJECT(stx,object)) {
hv = qse_stx_hash (
QSE_STX_DATA(stx,object), QSE_STX_SIZE(stx,object));
}
else {
qse_assert (QSE_STX_IS_WORD_OBJECT(stx,object));
hv = qse_stx_hash (QSE_STX_DATA(stx,object),
QSE_STX_SIZE(stx,object) * qse_sizeof(qse_word_t));
}
return hv;
}
qse_word_t qse_stx_instantiate (
qse_stx_t* stx, qse_word_t class, const void* data,
const void* variable_data, qse_word_t variable_nfields)
{
qse_stx_class_t* class_obj;
qse_word_t spec, nfields, new;
int indexable;
qse_assert (class != stx->class_smallinteger);
class_obj = (qse_stx_class_t*)QSE_STX_OBJECT(stx, class);
/* don't instantiate a metaclass whose instance must be
created in a different way */
/* TODO: maybe delete the following line */
qse_assert (class_obj->header.class != stx->class_metaclass);
qse_assert (QSE_STX_IS_SMALLINT(class_obj->spec));
spec = QSE_STX_FROM_SMALLINT(class_obj->spec);
nfields = (spec >> QSE_STX_SPEC_INDEXABLE_BITS);
indexable = spec & QSE_STX_SPEC_INDEXABLE_MASK;
if (indexable == QSE_STX_SPEC_BYTE_INDEXABLE) {
qse_assert (nfields == 0 && data == QSE_NULL);
new = qse_stx_alloc_byte_object(
stx, variable_data, variable_nfields);
}
else if (indexable == QSE_STX_SPEC_CHAR_INDEXABLE) {
qse_assert (nfields == 0 && data == QSE_NULL);
new = qse_stx_alloc_char_objectx(
stx, variable_data, variable_nfields);
}
else if (indexable == QSE_STX_SPEC_WORD_INDEXABLE) {
new = qse_stx_alloc_word_object (
stx, data, nfields, variable_data, variable_nfields);
}
else {
qse_assert (indexable == QSE_STX_SPEC_NOT_INDEXABLE);
qse_assert (variable_nfields == 0 && variable_data == QSE_NULL);
new = qse_stx_alloc_word_object (
stx, data, nfields, QSE_NULL, 0);
}
QSE_STX_CLASS(stx, new) = class;
return new;
}
qse_word_t qse_stx_class (qse_stx_t* stx, qse_word_t obj)
{
return QSE_STX_IS_SMALLINT(obj)?
stx->class_smallinteger: QSE_STX_CLASS(stx,obj);
}
qse_word_t qse_stx_classof (qse_stx_t* stx, qse_word_t obj)
{
return QSE_STX_IS_SMALLINT(obj)?
stx->class_smallinteger: QSE_STX_CLASS(stx,obj);
}
qse_word_t qse_stx_sizeof (qse_stx_t* stx, qse_word_t obj)
{
return QSE_STX_IS_SMALLINT(obj)? 1: QSE_STX_SIZE(stx,obj);
}

40
qse/lib/stx/object.h Normal file
View File

@ -0,0 +1,40 @@
/*
* $Id: object.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_OBJECT_H_
#define _QSE_STX_OBJECT_H_
#include <qse/stx/stx.h>
#ifdef __cplusplus
extern "C" {
#endif
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_hash_object (qse_stx_t* stx, qse_word_t object);
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);
qse_word_t qse_stx_classof (qse_stx_t* stx, qse_word_t obj);
qse_word_t qse_stx_sizeof (qse_stx_t* stx, qse_word_t obj);
#ifdef __cplusplus
}
#endif
#endif

1608
qse/lib/stx/parser.c Normal file

File diff suppressed because it is too large Load Diff

107
qse/lib/stx/parser.h Normal file
View File

@ -0,0 +1,107 @@
/*
* $Id: parser.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_PARSER_H_
#define _QSE_STX_PARSER_H_
#include <qse/stx/stx.h>
#include <qse/stx/name.h>
#include <qse/stx/token.h>
#include <qse/bas/arr.h>
enum
{
QSE_STX_PARSER_ERROR_NONE,
/* system errors */
QSE_STX_PARSER_ERROR_INPUT_FUNC,
QSE_STX_PARSER_ERROR_INPUT,
QSE_STX_PARSER_ERROR_MEMORY,
/* lexical errors */
QSE_STX_PARSER_ERROR_CHAR,
QSE_STX_PARSER_ERROR_CHARLIT,
QSE_STX_PARSER_ERROR_STRLIT,
QSE_STX_PARSER_ERROR_LITERAL,
/* syntatic error */
QSE_STX_PARSER_ERROR_MESSAGE_SELECTOR,
QSE_STX_PARSER_ERROR_ARGUMENT_NAME,
QSE_STX_PARSER_ERROR_TOO_MANY_ARGUMENTS,
QSE_STX_PARSER_ERROR_PRIMITIVE_KEYWORD,
QSE_STX_PARSER_ERROR_PRIMITIVE_NUMBER,
QSE_STX_PARSER_ERROR_PRIMITIVE_NUMBER_RANGE,
QSE_STX_PARSER_ERROR_PRIMITIVE_NOT_CLOSED,
QSE_STX_PARSER_ERROR_TEMPORARIES_NOT_CLOSED,
QSE_STX_PARSER_ERROR_TOO_MANY_TEMPORARIES,
QSE_STX_PARSER_ERROR_PSEUDO_VARIABLE,
QSE_STX_PARSER_ERROR_PRIMARY,
QSE_STX_PARSER_ERROR_NO_PERIOD,
QSE_STX_PARSER_ERROR_NO_RPAREN,
QSE_STX_PARSER_ERROR_BLOCK_ARGUMENT_NAME,
QSE_STX_PARSER_ERROR_BLOCK_ARGUMENT_LIST,
QSE_STX_PARSER_ERROR_BLOCK_NOT_CLOSED,
QSE_STX_PARSER_ERROR_UNDECLARED_NAME,
QSE_STX_PARSER_ERROR_TOO_MANY_LITERALS
};
enum
{
/* input_func cmd */
QSE_STX_PARSER_INPUT_OPEN,
QSE_STX_PARSER_INPUT_CLOSE,
QSE_STX_PARSER_INPUT_CONSUME,
QSE_STX_PARSER_INPUT_REWIND
};
typedef struct qse_stx_parser_t qse_stx_parser_t;
struct qse_stx_parser_t
{
qse_stx_t* stx;
int error_code;
qse_word_t method_class;
qse_stx_name_t method_name;
qse_char_t* temporaries[256]; /* TODO: different size? or dynamic? */
qse_word_t argument_count;
qse_word_t temporary_count;
qse_word_t literals[256]; /* TODO: make it a dynamic array */
qse_word_t literal_count;
qse_arr_t bytecode;
qse_stx_token_t token;
qse_cint_t curc;
qse_cint_t ungotc[5];
qse_size_t ungotc_count;
void* input_owner;
int (*input_func) (int cmd, void* owner, void* arg);
qse_bool_t __dynamic;
};
#ifdef __cplusplus
extern "C" {
#endif
qse_stx_parser_t* qse_stx_parser_open (qse_stx_parser_t* parser, qse_stx_t* stx);
void qse_stx_parser_close (qse_stx_parser_t* parser);
const qse_char_t* qse_stx_parser_error_string (qse_stx_parser_t* parser);
int qse_stx_parser_parse_method (
qse_stx_parser_t* parser, qse_word_t method_class, void* input);
#ifdef __cplusplus
}
#endif
#endif

196
qse/lib/stx/stx.bnf Normal file
View File

@ -0,0 +1,196 @@
~~~ method grammar ~~~
<method definition> ::=
<message pattern>
[<temporaries> ]
[<statements>]
<message pattern> ::= <unary pattern> |
<binary pattern> |
<keyword pattern>
<unary pattern> ::= unarySelector
<binary pattern> ::= binarySelector <method argument>
<keyword pattern> ::= (keyword <method argument>)+
<temporaries> ::= '|' <temporary variable list> '|'
<temporary variable list> ::= identifier*
<block constructor> ::= '[' <block body> ']'
<block body> ::= [<block argument>* '|']
[<temporaries>] [<statements>]
<block argument> ::= ':' identifier
<statements> ::=
(<return statement> ['.'] ) |
(<expression> ['.' [<statements>]])
<return statement> ::= returnOperator <expression>
<expression> ::=
<assignment> |
<basic expression>
<assignment> ::= <assignment target> assignmentOperator <expression>
<basic expression> ::=
<primary> [<messages> <cascaded messages>]
<assignment target> := identifier
<primary> ::=
identifier |
<literal> |
<block constructor> |
( '(' <expression> ')' )
<messages> ::=
(<unary message>+ <binary message>* [<keyword message>] ) |
(<binary message>+ [<keyword message>] ) |
<keyword message>
<unary message> ::= unarySelector
<binary message> ::= binarySelector <binary argument>
<binary argument> ::= <primary> <unary message>*
<keyword message> ::= (keyword <keyword argument> )+
<keyword argument> ::= <primary> <unary message>* <binary message>*
<cascaded messages> ::= (';' <messages>)*
<literal> ::=
<number literal> |
<string literal> |
<character literal> |
<symbol literal> |
<selector literal> |
<array literal>
<number literal> ::= ['-'] <number>
<number> ::= integer | float | scaledDecimal
<character literal> ::= quotedCharacter
<string literal> ::= quotedString
<symbol literal> ::= hashedString
<selector literal> ::= quotedSelector
<array literal> ::= '#(' <array element>* ')'
<array element> ::= <literal> | identifier
reserved identifiers -> nil true false self super
~~~ lexical grammar ~~~
character ::=
"Any character in the implementation-defined character set"
whitespace ::=
"Any non-printing character interpreted as white space
including spaces, tabs, and line breaks"
digit ::=
'0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
uppercaseAlphabetic ::=
'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' |
'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' |
'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'
lowercaseAlphabetic ::=
'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' |
'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' |
's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'
nonCaseLetter ::= '_'
letter ::=
uppercaseAlphabetic |
lowercaseAlphabetic |
nonCaseLetter |
"implementation defined letters"
commentDelimiter ::= '"'
nonCommentDelimiter::=
"any character that is not a commentDelimiter "
comment :=
commentDelimiter nonCommentDelimiter * commentDelimiter
identifier ::= letter (letter | digit)*
keyword ::= identifier ':'
binaryCharacter ::=
'!' | '%' | '&' | '*' | '+' | ',' |
'/' | '<' | '=' | '>' | '?' | '@' |
'\' | '~' | '|' | '-'
binarySelector ::= binaryCharacter+
returnOperator ::= '^'
assignmentOperator ::= ':='
integer ::= decimalInteger | radixInteger
decimalInteger ::= digits
digits ::= digit+
radixInteger ::= radixSpecifier 'r' radixDigits
radixSpecifier := digits
radixDigits ::= (digit | uppercaseAlphabetic)+
float ::= mantissa [exponentLetter exponent]
mantissa ::= digits'.' digits
exponent ::= ['-']decimalInteger
exponentLetter ::= 'e' | 'd' | 'q'
scaledDecimal ::= scaledMantissa 's' [fractionalDigits]
scaledMantissa ::= decimalInteger | mantissa
fractionalDigits ::= decimalInteger
quotedCharacter ::= '$' character
quotedString ::= stringDelimiter stringBody stringDelimiter
stringBody ::= (nonStringDelimiter | (stringDelimiter stringDelimiter)*)
stringDelimiter ::= ''' "a single quote"
nonStringDelimiter ::= "any character except stringDelimiter"
hashedString ::= '#' quotedString
quotedSelector ::= '#' (unarySelector | binarySelector | keywordSelector)
keywordSelector ::= keyword+
separator ::= (whitespace | comment)*

70
qse/lib/stx/stx.c Normal file
View File

@ -0,0 +1,70 @@
/*
* $Id: stx.c 118 2008-03-03 11:21:33Z baconevi $
*/
#include <qse/stx/stx.h>
#include <qse/stx/memory.h>
#include <qse/stx/misc.h>
qse_stx_t* qse_stx_open (qse_stx_t* stx, qse_word_t capacity)
{
qse_word_t i;
if (stx == QSE_NULL) {
stx = (qse_stx_t*)qse_malloc (qse_sizeof(stx));
if (stx == QSE_NULL) return QSE_NULL;
stx->__dynamic = qse_true;
}
else stx->__dynamic = qse_false;
if (qse_stx_memory_open (&stx->memory, capacity) == QSE_NULL) {
if (stx->__dynamic) qse_free (stx);
return QSE_NULL;
}
stx->symtab.size = 0;
stx->symtab.capacity = 128; /* TODO: symbol table size */
stx->symtab.datum = (qse_word_t*)qse_malloc (
qse_sizeof(qse_word_t) * stx->symtab.capacity);
if (stx->symtab.datum == QSE_NULL) {
qse_stx_memory_close (&stx->memory);
if (stx->__dynamic) qse_free (stx);
return QSE_NULL;
}
stx->nil = QSE_STX_NIL;
stx->true = QSE_STX_TRUE;
stx->false = QSE_STX_FALSE;
stx->smalltalk = QSE_STX_NIL;
stx->class_symbol = QSE_STX_NIL;
stx->class_metaclass = QSE_STX_NIL;
stx->class_association = QSE_STX_NIL;
stx->class_object = QSE_STX_NIL;
stx->class_class = QSE_STX_NIL;
stx->class_array = QSE_STX_NIL;
stx->class_bytearray = QSE_STX_NIL;
stx->class_string = QSE_STX_NIL;
stx->class_character = QSE_STX_NIL;
stx->class_context = QSE_STX_NIL;
stx->class_system_dictionary = QSE_STX_NIL;
stx->class_method = QSE_STX_NIL;
stx->class_smallinteger = QSE_STX_NIL;
for (i = 0; i < stx->symtab.capacity; i++) {
stx->symtab.datum[i] = stx->nil;
}
stx->__wantabort = qse_false;
return stx;
}
void qse_stx_close (qse_stx_t* stx)
{
qse_free (stx->symtab.datum);
qse_stx_memory_close (&stx->memory);
if (stx->__dynamic) qse_free (stx);
}

163
qse/lib/stx/stx.h Normal file
View File

@ -0,0 +1,163 @@
/*
* $Id: stx.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_STX_H_
#define _QSE_STX_STX_H_
#include <qse/cmn/types.h>
#include <qse/cmn/macros.h>
typedef struct qse_stx_objhdr_t qse_stx_objhdr_t;
typedef struct qse_stx_object_t qse_stx_object_t;
typedef struct qse_stx_word_object_t qse_stx_word_object_t;
typedef struct qse_stx_byte_object_t qse_stx_byte_object_t;
typedef struct qse_stx_char_object_t qse_stx_char_object_t;
typedef struct qse_stx_memory_t qse_stx_memory_t;
typedef struct qse_stx_symtab_t qse_stx_symtab_t;
typedef struct qse_stx_t qse_stx_t;
/* common object structure */
struct qse_stx_objhdr_t
{
/* access - type: 2; size: rest;
* type - word indexed: 00 byte indexed: 01 char indexed: 10
*/
qse_word_t access;
qse_word_t class;
};
struct qse_stx_object_t
{
qse_stx_objhdr_t header;
};
struct qse_stx_word_object_t
{
qse_stx_objhdr_t header;
qse_word_t data[1];
};
struct qse_stx_byte_object_t
{
qse_stx_objhdr_t header;
qse_byte_t data[1];
};
struct qse_stx_char_object_t
{
qse_stx_objhdr_t header;
qse_char_t data[1];
};
struct qse_stx_memory_t
{
qse_word_t capacity;
qse_stx_object_t** slots;
qse_stx_object_t** free;
qse_bool_t __dynamic;
};
struct qse_stx_symtab_t
{
qse_word_t* datum;
qse_word_t size;
qse_word_t capacity;
};
struct qse_stx_t
{
qse_stx_memory_t memory;
qse_stx_symtab_t symtab;
qse_word_t nil;
qse_word_t true;
qse_word_t false;
qse_word_t smalltalk;
qse_word_t class_symbol;
qse_word_t class_metaclass;
qse_word_t class_association;
qse_word_t class_object;
qse_word_t class_class;
qse_word_t class_array;
qse_word_t class_bytearray;
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_method;
qse_word_t class_smallinteger;
qse_bool_t __dynamic;
qse_bool_t __wantabort; /* TODO: make it a function pointer */
};
#define QSE_STX_IS_SMALLINT(x) (((x) & 0x01) == 0x01)
#define QSE_STX_TO_SMALLINT(x) (((x) << 1) | 0x01)
#define QSE_STX_FROM_SMALLINT(x) ((x) >> 1)
#define QSE_STX_IS_OINDEX(x) (((x) & 0x01) == 0x00)
#define QSE_STX_TO_OINDEX(x) (((x) << 1) | 0x00)
#define QSE_STX_FROM_OINDEX(x) ((x) >> 1)
#define QSE_STX_NIL QSE_STX_TO_OINDEX(0)
#define QSE_STX_TRUE QSE_STX_TO_OINDEX(1)
#define QSE_STX_FALSE QSE_STX_TO_OINDEX(2)
#define QSE_STX_OBJECT(stx,idx) (((stx)->memory).slots[QSE_STX_FROM_OINDEX(idx)])
#define QSE_STX_CLASS(stx,idx) (QSE_STX_OBJECT(stx,(idx))->header.class)
#define QSE_STX_ACCESS(stx,idx) (QSE_STX_OBJECT(stx,(idx))->header.access)
#define QSE_STX_DATA(stx,idx) ((void*)(QSE_STX_OBJECT(stx,idx) + 1))
#define QSE_STX_TYPE(stx,idx) (QSE_STX_ACCESS(stx,idx) & 0x03)
#define QSE_STX_SIZE(stx,idx) (QSE_STX_ACCESS(stx,idx) >> 0x02)
#define QSE_STX_WORD_INDEXED (0x00)
#define QSE_STX_BYTE_INDEXED (0x01)
#define QSE_STX_CHAR_INDEXED (0x02)
#define QSE_STX_IS_WORD_OBJECT(stx,idx) \
(QSE_STX_TYPE(stx,idx) == QSE_STX_WORD_INDEXED)
#define QSE_STX_IS_BYTE_OBJECT(stx,idx) \
(QSE_STX_TYPE(stx,idx) == QSE_STX_BYTE_INDEXED)
#define QSE_STX_IS_CHAR_OBJECT(stx,idx) \
(QSE_STX_TYPE(stx,idx) == QSE_STX_CHAR_INDEXED)
#define QSE_STX_WORD_OBJECT(stx,idx) \
((qse_stx_word_object_t*)QSE_STX_OBJECT(stx,idx))
#define QSE_STX_BYTE_OBJECT(stx,idx) \
((qse_stx_byte_object_t*)QSE_STX_OBJECT(stx,idx))
#define QSE_STX_CHAR_OBJECT(stx,idx) \
((qse_stx_char_object_t*)QSE_STX_OBJECT(stx,idx))
/*
#define QSE_STX_WORD_AT(stx,idx,n) \
(((qse_word_t*)(QSE_STX_OBJECT(stx,idx) + 1))[n])
#define QSE_STX_BYTE_AT(stx,idx,n) \
(((qse_byte_t*)(QSE_STX_OBJECT(stx,idx) + 1))[n])
#define QSE_STX_CHAR_AT(stx,idx,n) \
(((qse_char_t*)(QSE_STX_OBJECT(stx,idx) + 1))[n])
*/
#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])
#ifdef __cplusplus
extern "C" {
#endif
qse_stx_t* qse_stx_open (qse_stx_t* stx, qse_word_t capacity);
void qse_stx_close (qse_stx_t* stx);
#ifdef __cplusplus
}
#endif
#endif

90
qse/lib/stx/stx.txt Normal file
View File

@ -0,0 +1,90 @@
stx(1) qse
NAME
stx - qse smalltalk system
SYNOPSIS
stx [-f imageFile] MainClass
DESCRIPTION
The virtual machine executes "MainClass main" on start-up.
method 1.
push lookup_class(#MainClass) -> receiver.
send a unary(no argument) message with the selector #main.
return the returned value from main and exits.
method 2. - take a command parameter
push lookup_class(#MainClass) -> receiver.
push argc as an argument.
push argv as an argument.
send a double-argument message the the selector #main:withArgv:.
return the returned value from #main:withArgv and exits.
AUTHOR(S)
Hyung-Hwan Chung (bacon@abiyo.net) is the sole designer and implementer of stx.
BUG REPORTS
Report bugs to bacon@abiyo.net if you find any bugs. but make sure that it is really a bug before you report it.
COPYRIGHT
Copyright(c) 2005 bacon@abiyo.net
SEE ALSO
qse(7)
-- stack bytecodes --
0 0000 XXXX push_receiver_variable
1 0001 XXXX push_temporary_location
2 0010 XXXX push_literal_constant
3 0011 XXXX push_literal_variable
4 0100 XXXX store_receiver_variable
5 0101 XXXX store_temporary_location
6 0110 0000 XXXXXXXX push_receiver_variable_extended
0110 0001 XXXXXXXX push_temporary_location_extended
0110 0010 XXXXXXXX push_literal_constant_extended
0110 0011 XXXXXXXX push_literal_variable_extended
0110 0100 XXXXXXXX store_receiver_variable_extended
0110 0101 XXXXXXXX store_temporary_location_extended
0110 0110 unused
0110 0111 unused
0110 1000 pop_stack_top
0110 1001 duplicate_stack_top
0110 1010 push_active_context
0110 1011 unused
0110 1100 unused
0110 1101 unused
0110 1110 unused
0110 1111 unused
-- send bytecodes --
7 0111 0000 JJJKKKKK send_to_self
0111 0001 JJJKKKKK send_to_super
0111 0010 JJJJJJJJ KKKKKKKK send_to_self_extended
0111 0011 JJJJJJJJ KKKKKKKK send_to_super_extended
0111 0100 XXXXXXXX
0111 0101 XXXXXXXX
0111 0110 XXXXXXXX
0111 0111 XXXXXXXX
-- return bytecodes --
0111 1000 return receiver
0111 1001 return_true
0111 1010 return_false
0111 1011 return_nil
0111 1100 return_from_message
0111 1101 return_from_block
0111 1110
0111 1111
-- jump bytecodes --
8 1000 0XXX jump_forward
1000 1XXX XXXXXXXX jump_forward
-- primitive --
F 1111 XXXX XXXXXXXX do_primitive

102
qse/lib/stx/symbol.c Normal file
View File

@ -0,0 +1,102 @@
/*
* $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);
}
}

40
qse/lib/stx/symbol.h Normal file
View File

@ -0,0 +1,40 @@
/*
* $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

77
qse/lib/stx/token.c Normal file
View File

@ -0,0 +1,77 @@
/*
* $Id: token.c 118 2008-03-03 11:21:33Z baconevi $
*/
#include <qse/stx/token.h>
#include <qse/stx/misc.h>
qse_stx_token_t* qse_stx_token_open (
qse_stx_token_t* token, qse_word_t capacity)
{
if (token == QSE_NULL) {
token = (qse_stx_token_t*)
qse_malloc (qse_sizeof(qse_stx_token_t));
if (token == QSE_NULL) return QSE_NULL;
token->__dynamic = qse_true;
}
else token->__dynamic = qse_false;
if (qse_stx_name_open(&token->name, capacity) == QSE_NULL) {
if (token->__dynamic) qse_free (token);
return QSE_NULL;
}
/*
token->ivalue = 0;
token->fvalue = .0;
*/
token->type = QSE_STX_TOKEN_END;
return token;
}
void qse_stx_token_close (qse_stx_token_t* token)
{
qse_stx_name_close (&token->name);
if (token->__dynamic) qse_free (token);
}
int qse_stx_token_addc (qse_stx_token_t* token, qse_cint_t c)
{
return qse_stx_name_addc (&token->name, c);
}
int qse_stx_token_adds (qse_stx_token_t* token, const qse_char_t* s)
{
return qse_stx_name_adds (&token->name, s);
}
void qse_stx_token_clear (qse_stx_token_t* token)
{
/*
token->ivalue = 0;
token->fvalue = .0;
*/
token->type = QSE_STX_TOKEN_END;
qse_stx_name_clear (&token->name);
}
qse_char_t* qse_stx_token_yield (qse_stx_token_t* token, qse_word_t capacity)
{
qse_char_t* p;
p = qse_stx_name_yield (&token->name, capacity);
if (p == QSE_NULL) return QSE_NULL;
/*
token->ivalue = 0;
token->fvalue = .0;
*/
token->type = QSE_STX_TOKEN_END;
return p;
}
int qse_stx_token_compare_name (qse_stx_token_t* token, const qse_char_t* str)
{
return qse_stx_name_compare (&token->name, str);
}

66
qse/lib/stx/token.h Normal file
View File

@ -0,0 +1,66 @@
/*
* $Id: token.h 118 2008-03-03 11:21:33Z baconevi $
*/
#ifndef _QSE_STX_TOKEN_H_
#define _QSE_STX_TOKEN_H_
#include <qse/stx/stx.h>
#include <qse/stx/name.h>
enum
{
QSE_STX_TOKEN_END,
QSE_STX_TOKEN_CHARLIT,
QSE_STX_TOKEN_STRLIT,
QSE_STX_TOKEN_SYMLIT,
QSE_STX_TOKEN_NUMLIT,
QSE_STX_TOKEN_IDENT,
QSE_STX_TOKEN_BINARY,
QSE_STX_TOKEN_KEYWORD,
QSE_STX_TOKEN_PRIMITIVE,
QSE_STX_TOKEN_ASSIGN,
QSE_STX_TOKEN_COLON,
QSE_STX_TOKEN_RETURN,
QSE_STX_TOKEN_LBRACKET,
QSE_STX_TOKEN_RBRACKET,
QSE_STX_TOKEN_LPAREN,
QSE_STX_TOKEN_RPAREN,
QSE_STX_TOKEN_APAREN,
QSE_STX_TOKEN_PERIOD,
QSE_STX_TOKEN_SEMICOLON
};
struct qse_stx_token_t
{
int type;
/*
qse_stx_int_t ivalue;
qse_stx_real_t fvalue;
*/
qse_stx_name_t name;
qse_bool_t __dynamic;
};
typedef struct qse_stx_token_t qse_stx_token_t;
#ifdef __cplusplus
extern "C" {
#endif
qse_stx_token_t* qse_stx_token_open (
qse_stx_token_t* token, qse_word_t capacity);
void qse_stx_token_close (qse_stx_token_t* token);
int qse_stx_token_addc (qse_stx_token_t* token, qse_cint_t c);
int qse_stx_token_adds (qse_stx_token_t* token, const qse_char_t* s);
void qse_stx_token_clear (qse_stx_token_t* token);
qse_char_t* qse_stx_token_yield (qse_stx_token_t* token, qse_word_t capacity);
int qse_stx_token_compare_name (qse_stx_token_t* token, const qse_char_t* str);
#ifdef __cplusplus
}
#endif
#endif