Recovered from cvs revision 2007-05-01 07:40:00

This commit is contained in:
2007-05-02 01:07:00 +00:00
parent 76daf75d92
commit e1b2079906
474 changed files with 99385 additions and 0 deletions

18
ase/stx/array.c Normal file
View File

@ -0,0 +1,18 @@
/*
* $Id: array.c,v 1.3 2007/04/30 08:32:40 bacon Exp $
*/
#include <ase/stx/array.h>
#include <ase/stx/object.h>
#include <ase/bas/assert.h>
ase_word_t ase_stx_new_array (ase_stx_t* stx, ase_word_t size)
{
ase_word_t x;
ase_assert (stx->class_array != stx->nil);
x = ase_stx_alloc_word_object (stx, ASE_NULL, 0, ASE_NULL, size);
ASE_STX_CLASS(stx,x) = stx->class_array;
return x;
}

21
ase/stx/array.h Normal file
View File

@ -0,0 +1,21 @@
/*
* $Id: array.h,v 1.3 2007/04/30 08:32:40 bacon Exp $
*/
#ifndef _ASE_STX_ARRAY_H_
#define _ASE_STX_ARRAY_H_
#include <ase/stx/stx.h>
#ifdef __cplusplus
extern "C" {
#endif
ase_word_t ase_stx_new_array (ase_stx_t* stx, ase_word_t size);
#ifdef __cplusplus
}
#endif
#endif

676
ase/stx/bootstrp.c Normal file
View File

@ -0,0 +1,676 @@
/*
* $Id: bootstrp.c,v 1.3 2007/04/30 08:32:40 bacon Exp $
*/
#include <ase/stx/bootstrp.h>
#include <ase/stx/symbol.h>
#include <ase/stx/class.h>
#include <ase/stx/object.h>
#include <ase/stx/dict.h>
#include <ase/stx/misc.h>
static void __create_bootstrapping_objects (ase_stx_t* stx);
static void __create_builtin_classes (ase_stx_t* stx);
static ase_word_t __make_classvar_dict (
ase_stx_t* stx, ase_word_t class, const ase_char_t* names);
static void __filein_kernel (ase_stx_t* stx);
static ase_word_t __count_names (const ase_char_t* str);
static void __set_names (
ase_stx_t* stx, ase_word_t* array, const ase_char_t* str);
static ase_word_t __count_subclasses (const ase_char_t* str);
static void __set_subclasses (
ase_stx_t* stx, ase_word_t* array, const ase_char_t* str);
static void __set_metaclass_subclasses (
ase_stx_t* stx, ase_word_t* array, const ase_char_t* str);
struct class_info_t
{
const ase_char_t* name;
const ase_char_t* superclass;
const ase_char_t* instance_variables;
const ase_char_t* class_variables;
const ase_char_t* pool_dictionaries;
const int indexable;
};
typedef struct class_info_t class_info_t;
static class_info_t class_info[] =
{
{
ASE_T("Object"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("UndefinedObject"),
ASE_T("Object"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Behavior"),
ASE_T("Object"),
ASE_T("spec methods superclass"),
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Class"),
ASE_T("Behavior"),
ASE_T("name variables classVariables poolDictionaries"),
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Metaclass"),
ASE_T("Behavior"),
ASE_T("instanceClass"),
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Block"),
ASE_T("Object"),
ASE_T("context argCount argLoc bytePointer"),
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Boolean"),
ASE_T("Object"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("True"),
ASE_T("Boolean"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("False"),
ASE_T("Boolean"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Context"),
ASE_T("Object"),
ASE_T("stack stackTop receiver pc method"),
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Method"),
ASE_T("Object"),
ASE_T("text selector bytecodes tmpCount argCount"),
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_WORD_INDEXABLE
},
{
ASE_T("Magnitude"),
ASE_T("Object"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Association"),
ASE_T("Magnitude"),
ASE_T("key value"),
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Character"),
ASE_T("Magnitude"),
ASE_T("value"),
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Number"),
ASE_T("Magnitude"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Integer"),
ASE_T("Number"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("SmallInteger"),
ASE_T("Integer"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("LargeInteger"),
ASE_T("Integer"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_BYTE_INDEXABLE
},
{
ASE_T("Collection"),
ASE_T("Magnitude"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("IndexedCollection"),
ASE_T("Collection"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_T("Array"),
ASE_T("IndexedCollection"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_WORD_INDEXABLE
},
{
ASE_T("ByteArray"),
ASE_T("IndexedCollection"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_BYTE_INDEXABLE
},
{
ASE_T("Dictionary"),
ASE_T("IndexedCollection"),
ASE_T("tally"),
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_WORD_INDEXABLE
},
{
ASE_T("SystemDictionary"),
ASE_T("Dictionary"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_WORD_INDEXABLE
},
{
ASE_T("PoolDictionary"),
ASE_T("Dictionary"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_WORD_INDEXABLE
},
{
ASE_T("String"),
ASE_T("IndexedCollection"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_CHAR_INDEXABLE
},
{
ASE_T("Symbol"),
ASE_T("String"),
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_CHAR_INDEXABLE
},
{
ASE_T("Link"),
ASE_T("Object"),
ASE_T("link"),
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
},
{
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_NULL,
ASE_STX_SPEC_NOT_INDEXABLE
}
};
ase_word_t INLINE __new_string (ase_stx_t* stx, const ase_char_t* str)
{
ase_word_t x;
ase_assert (stx->class_string != stx->nil);
x = ase_stx_alloc_char_object (stx, str);
ASE_STX_CLASS(stx,x) = stx->class_string;
return x;
}
int ase_stx_bootstrap (ase_stx_t* stx)
{
ase_word_t symbol_Smalltalk;
ase_word_t object_meta;
__create_bootstrapping_objects (stx);
/* object, class, and array are precreated for easier instantiation
* of builtin classes */
stx->class_object = ase_stx_new_class (stx, ASE_T("Object"));
stx->class_class = ase_stx_new_class (stx, ASE_T("Class"));
stx->class_array = ase_stx_new_class (stx, ASE_T("Array"));
stx->class_bytearray = ase_stx_new_class (stx, ASE_T("ByteArray"));
stx->class_string = ase_stx_new_class (stx, ASE_T("String"));
stx->class_character = ase_stx_new_class (stx, ASE_T("Character"));
stx->class_context = ase_stx_new_class (stx, ASE_T("Context"));
stx->class_system_dictionary =
ase_stx_new_class (stx, ASE_T("SystemDictionary"));
stx->class_method =
ase_stx_new_class (stx, ASE_T("Method"));
stx->class_smallinteger =
ase_stx_new_class (stx, ASE_T("SmallInteger"));
__create_builtin_classes (stx);
/* (Object class) setSuperclass: Class */
object_meta = ASE_STX_CLASS(stx,stx->class_object);
ASE_STX_WORD_AT(stx,object_meta,ASE_STX_METACLASS_SUPERCLASS) = stx->class_class;
/* instance class for Object is set here as it is not
* set in __create_builtin_classes */
ASE_STX_WORD_AT(stx,object_meta,ASE_STX_METACLASS_INSTANCE_CLASS) = stx->class_object;
/* for some fun here */
{
ase_word_t array;
array = ase_stx_new_array (stx, 1);
ASE_STX_WORD_AT(stx,array,0) = object_meta;
ASE_STX_WORD_AT(stx,stx->class_class,ASE_STX_CLASS_SUBCLASSES) = array;
}
/* more initialization */
ASE_STX_CLASS(stx,stx->smalltalk) = stx->class_system_dictionary;
symbol_Smalltalk = ase_stx_new_symbol (stx, ASE_T("Smalltalk"));
ase_stx_dict_put (stx, stx->smalltalk, symbol_Smalltalk, stx->smalltalk);
/* create #nil, #true, #false */
ase_stx_new_symbol (stx, ASE_T("nil"));
ase_stx_new_symbol (stx, ASE_T("true"));
ase_stx_new_symbol (stx, ASE_T("false"));
/* nil setClass: UndefinedObject */
ASE_STX_CLASS(stx,stx->nil) =
ase_stx_lookup_class(stx, ASE_T("UndefinedObject"));
/* true setClass: True */
ASE_STX_CLASS(stx,stx->true) =
ase_stx_lookup_class (stx, ASE_T("True"));
/* fales setClass: False */
ASE_STX_CLASS(stx,stx->false) =
ase_stx_lookup_class (stx, ASE_T("False"));
__filein_kernel (stx);
return 0;
}
static void __create_bootstrapping_objects (ase_stx_t* stx)
{
ase_word_t class_SymbolMeta;
ase_word_t class_MetaclassMeta;
ase_word_t class_AssociationMeta;
ase_word_t symbol_Symbol;
ase_word_t symbol_Metaclass;
ase_word_t symbol_Association;
/* allocate three keyword objects */
stx->nil = ase_stx_alloc_word_object (stx, ASE_NULL, 0, ASE_NULL, 0);
stx->true = ase_stx_alloc_word_object (stx, ASE_NULL, 0, ASE_NULL, 0);
stx->false = ase_stx_alloc_word_object (stx, ASE_NULL, 0, ASE_NULL, 0);
ase_assert (stx->nil == ASE_STX_NIL);
ase_assert (stx->true == ASE_STX_TRUE);
ase_assert (stx->false == ASE_STX_FALSE);
/* system dictionary */
/* TODO: dictionary size */
stx->smalltalk = ase_stx_alloc_word_object (
stx, ASE_NULL, 1, ASE_NULL, 256);
/* set tally */
ASE_STX_WORD_AT(stx,stx->smalltalk,0) = ASE_STX_TO_SMALLINT(0);
/* Symbol */
stx->class_symbol = ase_stx_alloc_word_object(
stx, ASE_NULL, ASE_STX_CLASS_SIZE, ASE_NULL, 0);
/* Metaclass */
stx->class_metaclass = ase_stx_alloc_word_object(
stx, ASE_NULL, ASE_STX_CLASS_SIZE, ASE_NULL, 0);
/* Association */
stx->class_association = ase_stx_alloc_word_object(
stx, ASE_NULL, ASE_STX_CLASS_SIZE, ASE_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 = ase_stx_alloc_word_object(
stx, ASE_NULL, ASE_STX_METACLASS_SIZE, ASE_NULL, 0);
/* Metaclass class */
class_MetaclassMeta = ase_stx_alloc_word_object(
stx, ASE_NULL, ASE_STX_METACLASS_SIZE, ASE_NULL, 0);
/* Association class */
class_AssociationMeta = ase_stx_alloc_word_object(
stx, ASE_NULL, ASE_STX_METACLASS_SIZE, ASE_NULL, 0);
/* (Symbol class) setClass: Metaclass */
ASE_STX_CLASS(stx,class_SymbolMeta) = stx->class_metaclass;
/* (Metaclass class) setClass: Metaclass */
ASE_STX_CLASS(stx,class_MetaclassMeta) = stx->class_metaclass;
/* (Association class) setClass: Metaclass */
ASE_STX_CLASS(stx,class_AssociationMeta) = stx->class_metaclass;
/* Symbol setClass: (Symbol class) */
ASE_STX_CLASS(stx,stx->class_symbol) = class_SymbolMeta;
/* Metaclass setClass: (Metaclass class) */
ASE_STX_CLASS(stx,stx->class_metaclass) = class_MetaclassMeta;
/* Association setClass: (Association class) */
ASE_STX_CLASS(stx,stx->class_association) = class_AssociationMeta;
/* (Symbol class) setSpec: CLASS_SIZE */
ASE_STX_WORD_AT(stx,class_SymbolMeta,ASE_STX_CLASS_SPEC) =
ASE_STX_TO_SMALLINT((ASE_STX_CLASS_SIZE << ASE_STX_SPEC_INDEXABLE_BITS) | ASE_STX_SPEC_NOT_INDEXABLE);
/* (Metaclass class) setSpec: CLASS_SIZE */
ASE_STX_WORD_AT(stx,class_MetaclassMeta,ASE_STX_CLASS_SPEC) =
ASE_STX_TO_SMALLINT((ASE_STX_CLASS_SIZE << ASE_STX_SPEC_INDEXABLE_BITS) | ASE_STX_SPEC_NOT_INDEXABLE);
/* (Association class) setSpec: CLASS_SIZE */
ASE_STX_WORD_AT(stx,class_AssociationMeta,ASE_STX_CLASS_SPEC) =
ASE_STX_TO_SMALLINT((ASE_STX_CLASS_SIZE << ASE_STX_SPEC_INDEXABLE_BITS) | ASE_STX_SPEC_NOT_INDEXABLE);
/* specs for class_metaclass, class_association,
* class_symbol are set later in __create_builtin_classes */
/* #Symbol */
symbol_Symbol = ase_stx_new_symbol (stx, ASE_T("Symbol"));
/* #Metaclass */
symbol_Metaclass = ase_stx_new_symbol (stx, ASE_T("Metaclass"));
/* #Association */
symbol_Association = ase_stx_new_symbol (stx, ASE_T("Association"));
/* Symbol setName: #Symbol */
ASE_STX_WORD_AT(stx,stx->class_symbol,ASE_STX_CLASS_NAME) = symbol_Symbol;
/* Metaclass setName: #Metaclass */
ASE_STX_WORD_AT(stx,stx->class_metaclass,ASE_STX_CLASS_NAME) = symbol_Metaclass;
/* Association setName: #Association */
ASE_STX_WORD_AT(stx,stx->class_association,ASE_STX_CLASS_NAME) = symbol_Association;
/* register class names into the system dictionary */
ase_stx_dict_put (stx,
stx->smalltalk, symbol_Symbol, stx->class_symbol);
ase_stx_dict_put (stx,
stx->smalltalk, symbol_Metaclass, stx->class_metaclass);
ase_stx_dict_put (stx,
stx->smalltalk, symbol_Association, stx->class_association);
}
static void __create_builtin_classes (ase_stx_t* stx)
{
class_info_t* p;
ase_word_t class, superclass, array;
ase_stx_class_t* class_obj, * superclass_obj;
ase_word_t metaclass;
ase_stx_metaclass_t* metaclass_obj;
ase_word_t n, nfields;
ase_assert (stx->class_array != stx->nil);
for (p = class_info; p->name != ASE_NULL; p++) {
class = ase_stx_lookup_class(stx, p->name);
if (class == stx->nil) {
class = ase_stx_new_class (stx, p->name);
}
ase_assert (class != stx->nil);
class_obj = (ase_stx_class_t*)ASE_STX_OBJECT(stx, class);
class_obj->superclass = (p->superclass == ASE_NULL)?
stx->nil: ase_stx_lookup_class(stx,p->superclass);
nfields = 0;
if (p->superclass != ASE_NULL) {
ase_word_t meta;
ase_stx_metaclass_t* meta_obj;
superclass = ase_stx_lookup_class(stx,p->superclass);
ase_assert (superclass != stx->nil);
meta = class_obj->header.class;
meta_obj = (ase_stx_metaclass_t*)ASE_STX_OBJECT(stx,meta);
meta_obj->superclass = ASE_STX_CLASS(stx,superclass);
meta_obj->instance_class = class;
while (superclass != stx->nil) {
superclass_obj = (ase_stx_class_t*)
ASE_STX_OBJECT(stx,superclass);
nfields +=
ASE_STX_FROM_SMALLINT(superclass_obj->spec) >>
ASE_STX_SPEC_INDEXABLE_BITS;
superclass = superclass_obj->superclass;
}
}
if (p->instance_variables != ASE_NULL) {
nfields += __count_names (p->instance_variables);
class_obj->variables =
__new_string (stx, p->instance_variables);
}
ase_assert (nfields <= 0 || (nfields > 0 &&
(p->indexable == ASE_STX_SPEC_NOT_INDEXABLE ||
p->indexable == ASE_STX_SPEC_WORD_INDEXABLE)));
class_obj->spec = ASE_STX_TO_SMALLINT(
(nfields << ASE_STX_SPEC_INDEXABLE_BITS) | p->indexable);
}
for (p = class_info; p->name != ASE_NULL; p++) {
class = ase_stx_lookup_class(stx, p->name);
ase_assert (class != stx->nil);
class_obj = (ase_stx_class_t*)ASE_STX_OBJECT(stx, class);
if (p->class_variables != ASE_NULL) {
class_obj->class_variables =
__make_classvar_dict(stx, class, p->class_variables);
}
/*
TODO:
if (p->pool_dictionaries != ASE_NULL) {
class_obj->pool_dictionaries =
__make_pool_dictionary(stx, class, p->pool_dictionaries);
}
*/
}
/* fill subclasses */
for (p = class_info; p->name != ASE_NULL; p++) {
n = __count_subclasses (p->name);
array = ase_stx_new_array (stx, n);
__set_subclasses (stx, ASE_STX_DATA(stx,array), p->name);
class = ase_stx_lookup_class(stx, p->name);
ase_assert (class != stx->nil);
class_obj = (ase_stx_class_t*)ASE_STX_OBJECT(stx, class);
class_obj->subclasses = array;
}
/* fill subclasses for metaclasses */
for (p = class_info; p->name != ASE_NULL; p++) {
n = __count_subclasses (p->name);
array = ase_stx_new_array (stx, n);
__set_metaclass_subclasses (stx, ASE_STX_DATA(stx,array), p->name);
class = ase_stx_lookup_class(stx, p->name);
ase_assert (class != stx->nil);
metaclass = ASE_STX_CLASS(stx,class);
metaclass_obj = (ase_stx_metaclass_t*)ASE_STX_OBJECT(stx, metaclass);
metaclass_obj->subclasses = array;
}
}
static ase_word_t __count_names (const ase_char_t* str)
{
ase_word_t n = 0;
const ase_char_t* p = str;
do {
while (*p == ASE_T(' ') ||
*p == ASE_T('\t')) p++;
if (*p == ASE_T('\0')) break;
n++;
while (*p != ASE_T(' ') &&
*p != ASE_T('\t') &&
*p != ASE_T('\0')) p++;
} while (1);
return n;
}
static void __set_names (
ase_stx_t* stx, ase_word_t* array, const ase_char_t* str)
{
ase_word_t n = 0;
const ase_char_t* p = str;
const ase_char_t* name;
do {
while (*p == ASE_T(' ') ||
*p == ASE_T('\t')) p++;
if (*p == ASE_T('\0')) break;
name = p;
while (*p != ASE_T(' ') &&
*p != ASE_T('\t') &&
*p != ASE_T('\0')) p++;
array[n++] = ase_stx_new_symbolx (stx, name, p - name);
} while (1);
}
static ase_word_t __count_subclasses (const ase_char_t* str)
{
class_info_t* p;
ase_word_t n = 0;
for (p = class_info; p->name != ASE_NULL; p++) {
if (p->superclass == ASE_NULL) continue;
if (ase_strcmp (str, p->superclass) == 0) n++;
}
return n;
}
static void __set_subclasses (
ase_stx_t* stx, ase_word_t* array, const ase_char_t* str)
{
class_info_t* p;
ase_word_t n = 0, class;
for (p = class_info; p->name != ASE_NULL; p++) {
if (p->superclass == ASE_NULL) continue;
if (ase_strcmp (str, p->superclass) != 0) continue;
class = ase_stx_lookup_class (stx, p->name);
ase_assert (class != stx->nil);
array[n++] = class;
}
}
static void __set_metaclass_subclasses (
ase_stx_t* stx, ase_word_t* array, const ase_char_t* str)
{
class_info_t* p;
ase_word_t n = 0, class;
for (p = class_info; p->name != ASE_NULL; p++) {
if (p->superclass == ASE_NULL) continue;
if (ase_strcmp (str, p->superclass) != 0) continue;
class = ase_stx_lookup_class (stx, p->name);
ase_assert (class != stx->nil);
array[n++] = ASE_STX_CLASS(stx,class);
}
}
static ase_word_t __make_classvar_dict (
ase_stx_t* stx, ase_word_t class, const ase_char_t* names)
{
ase_word_t dict, symbol;
const ase_char_t* p = names;
const ase_char_t* name;
dict = ase_stx_instantiate (
stx, stx->class_system_dictionary,
ASE_NULL, ASE_NULL, __count_names(names));
do {
while (*p == ASE_T(' ') ||
*p == ASE_T('\t')) p++;
if (*p == ASE_T('\0')) break;
name = p;
while (*p != ASE_T(' ') &&
*p != ASE_T('\t') &&
*p != ASE_T('\0')) p++;
symbol = ase_stx_new_symbolx (stx, name, p - name);
ase_stx_dict_put (stx, dict, symbol, stx->nil);
} while (1);
return dict;
}
static void __filein_kernel (ase_stx_t* stx)
{
class_info_t* p;
for (p = class_info; p->name != ASE_NULL; p++) {
/* TODO: */
}
}

21
ase/stx/bootstrp.h Normal file
View File

@ -0,0 +1,21 @@
/*
* $Id: bootstrp.h,v 1.3 2007/04/30 08:32:40 bacon Exp $
*/
#ifndef _ASE_STX_BOOTSTRP_H_
#define _ASE_STX_BOOTSTRP_H_
#include <ase/stx/stx.h>
#ifdef __cplusplus
extern "C" {
#endif
ase_word_t ase_stx_new_array (ase_stx_t* stx, ase_word_t size);
int ase_stx_bootstrap (ase_stx_t* stx);
#ifdef __cplusplus
}
#endif
#endif

193
ase/stx/bytecode.c Normal file
View File

@ -0,0 +1,193 @@
/*
* $Id: bytecode.c,v 1.3 2007/04/30 08:32:40 bacon Exp $
*/
#include <ase/stx/bytecode.h>
#include <ase/stx/class.h>
#include <ase/stx/method.h>
#include <ase/stx/dict.h>
static void __decode1 (ase_stx_t* stx, ase_word_t idx, void* data);
static int __decode2 (ase_stx_t* stx,
ase_stx_class_t* class_obj, ase_stx_method_t* method_obj);
int ase_stx_decode (ase_stx_t* stx, ase_word_t class)
{
ase_stx_class_t* class_obj;
class_obj = (ase_stx_class_t*)ASE_STX_OBJECT(stx, class);
if (class_obj->methods == stx->nil) return 0;
/* TODO */
ase_stx_dict_traverse (stx, class_obj->methods, __decode1, class_obj);
return 0;
}
#include <ase/bas/stdio.h>
static void __dump_object (ase_stx_t* stx, ase_word_t obj)
{
if (ASE_STX_IS_SMALLINT(obj)) {
ase_printf (ASE_T("%d"), ASE_STX_FROM_SMALLINT(obj));
}
else if (ASE_STX_CLASS(stx,obj) == stx->class_character) {
ase_printf (ASE_T("$%c"), ASE_STX_WORD_AT(stx,obj,0));
}
else if (ASE_STX_CLASS(stx,obj) == stx->class_string) {
ase_printf (ASE_T("'%s'"), ASE_STX_DATA(stx,obj));
}
else if (ASE_STX_CLASS(stx,obj) == stx->class_symbol) {
ase_printf (ASE_T("#%s"), ASE_STX_DATA(stx,obj));
}
else if (ASE_STX_IS_CHAR_OBJECT(stx, obj)) {
ase_printf (ASE_T("unknow char object [%s]"), ASE_STX_DATA(stx,obj));
}
else if (ASE_STX_IS_BYTE_OBJECT(stx, obj)) {
ase_printf (ASE_T("unknown byte object"), ASE_STX_DATA(stx,obj));
}
else if (ASE_STX_IS_WORD_OBJECT(stx, obj)) {
ase_printf (ASE_T("unknown word object"), ASE_STX_DATA(stx,obj));
}
else {
ase_printf (ASE_T("invalid object type"));
}
}
static void __decode1 (ase_stx_t* stx, ase_word_t idx, void* data)
{
ase_stx_method_t* method_obj;
ase_stx_class_t* class_obj;
ase_word_t key = ASE_STX_WORD_AT(stx,idx,ASE_STX_ASSOCIATION_KEY);
ase_word_t value = ASE_STX_WORD_AT(stx,idx,ASE_STX_ASSOCIATION_VALUE);
ase_word_t* literals;
ase_word_t literal_count, i;
ase_word_t method_class;
ase_stx_class_t* method_class_obj;
class_obj = (ase_stx_class_t*)data;
ase_printf (ASE_T("* Method: %s\n"), ASE_STX_DATA(stx, key));
method_obj = (ase_stx_method_t*)ASE_STX_OBJECT(stx, value);
literals = method_obj->literals;
/*
literal_count = ASE_STX_SIZE(stx, value) -
(ASE_STX_FROM_SMALLINT(class_obj->spec) >> ASE_STX_SPEC_INDEXABLE_BITS);
*/
method_class = ASE_STX_CLASS(stx,value);
method_class_obj = ASE_STX_OBJECT(stx, method_class);
literal_count = ASE_STX_SIZE(stx,value) -
(ASE_STX_FROM_SMALLINT(method_class_obj->spec) >> ASE_STX_SPEC_INDEXABLE_BITS);
ase_printf (ASE_T("* Literal Count: %d, Temporary Count: %d, Argument Count: %d\n"),
literal_count,
ASE_STX_FROM_SMALLINT(method_obj->tmpcount),
ASE_STX_FROM_SMALLINT(method_obj->argcount));
for (i = 0; i < literal_count; i++) {
ase_printf (ASE_T("%d. ["), i);
__dump_object (stx, literals[i]);
ase_printf (ASE_T("]\n"));
}
__decode2 (stx, data, method_obj);
}
static int __decode2 (ase_stx_t* stx,
ase_stx_class_t* class_obj, ase_stx_method_t* method_obj)
{
ase_stx_byte_object_t* bytecodes;
ase_word_t bytecode_size, pc = 0;
int code, next, next2;
static const ase_char_t* stack_opcode_names[] =
{
ASE_T("push_receiver_variable"),
ASE_T("push_temporary_location"),
ASE_T("push_literal_constant"),
ASE_T("push_literal_variable"),
ASE_T("store_receiver_variable"),
ASE_T("store_temporary_location")
};
static const ase_char_t* send_opcode_names[] =
{
ASE_T("send_to_self"),
ASE_T("send_to_super")
};
static const ase_char_t* stack_special_opcode_names[] =
{
ASE_T("pop_stack_top"),
ASE_T("duplicate_pop_stack_top"),
ASE_T("push_active_context"),
ASE_T("push_nil"),
ASE_T("push_true"),
ASE_T("push_false"),
ASE_T("push_receiver")
};
static const ase_char_t* return_opcode_names[] =
{
ASE_T("return_receiver"),
ASE_T("return_true"),
ASE_T("return_false"),
ASE_T("return_nil"),
ASE_T("return_from_message"),
ASE_T("return_from_block")
};
bytecodes = ASE_STX_BYTE_OBJECT(stx, method_obj->bytecodes);
bytecode_size = ASE_STX_SIZE(stx, method_obj->bytecodes);
while (pc < bytecode_size) {
code = bytecodes->data[pc++];
if (code >= 0x00 && code <= 0x5F) {
/* stack */
ase_printf (ASE_T("%s %d\n"),
stack_opcode_names[code >> 4], code & 0x0F);
}
else if (code >= 0x60 && code <= 0x65) {
/* stack extended */
next = bytecodes->data[pc++];
ase_printf (ASE_T("%s %d\n"),
stack_opcode_names[code & 0x0F], next);
}
else if (code >= 0x67 && code <= 0x6D) {
/* stack special */
ase_printf (ASE_T("%s\n"),
stack_special_opcode_names[code - 0x67]);
}
else if (code >= 0x70 && code <= 0x71 ) {
/* send message */
next = bytecodes->data[pc++];
ase_printf (ASE_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++];
ase_printf (ASE_T("%s %d %d\n"),
send_opcode_names[code - 0x72], next, next2);
}
else if (code >= 0x78 && code <= 0x7D) {
ase_printf (ASE_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++];
ase_printf (ASE_T("do_primitive %d\n"), ((code & 0x0F) << 8) | next);
}
else {
ase_printf (ASE_T("unknown byte code 0x%x\n"), code);
}
}
return 0;
}

56
ase/stx/bytecode.h Normal file
View File

@ -0,0 +1,56 @@
/*
* $Id: bytecode.h,v 1.3 2007/04/30 08:32:40 bacon Exp $
*/
#ifndef _ASE_STX_BYTECODE_H_
#define _ASE_STX_BYTECODE_H_
#include <ase/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 ase_stx_decode (ase_stx_t* stx, ase_word_t class_idx);
#ifdef __cplusplus
}
#endif
#endif

168
ase/stx/class.c Normal file
View File

@ -0,0 +1,168 @@
/*
* $Id: class.c,v 1.3 2007/04/30 08:32:40 bacon Exp $
*/
#include <ase/stx/class.h>
#include <ase/stx/symbol.h>
#include <ase/stx/object.h>
#include <ase/stx/dict.h>
#include <ase/stx/misc.h>
ase_word_t ase_stx_new_class (ase_stx_t* stx, const ase_char_t* name)
{
ase_word_t meta, class;
ase_word_t class_name;
meta = ase_stx_alloc_word_object (
stx, ASE_NULL, ASE_STX_METACLASS_SIZE, ASE_NULL, 0);
ASE_STX_CLASS(stx,meta) = stx->class_metaclass;
/* the spec of the metaclass must be the spec of its
* instance. so the ASE_STX_CLASS_SIZE is set */
ASE_STX_WORD_AT(stx,meta,ASE_STX_METACLASS_SPEC) =
ASE_STX_TO_SMALLINT((ASE_STX_CLASS_SIZE << ASE_STX_SPEC_INDEXABLE_BITS) | ASE_STX_SPEC_NOT_INDEXABLE);
/* the spec of the class is set later in __create_builtin_classes */
class = ase_stx_alloc_word_object (
stx, ASE_NULL, ASE_STX_CLASS_SIZE, ASE_NULL, 0);
ASE_STX_CLASS(stx,class) = meta;
class_name = ase_stx_new_symbol (stx, name);
ASE_STX_WORD_AT(stx,class,ASE_STX_CLASS_NAME) = class_name;
ase_stx_dict_put (stx, stx->smalltalk, class_name, class);
return class;
}
ase_word_t ase_stx_lookup_class (ase_stx_t* stx, const ase_char_t* name)
{
ase_word_t assoc, meta, value;
assoc = ase_stx_dict_lookup (stx, stx->smalltalk, name);
if (assoc == stx->nil) {
return stx->nil;
}
value = ASE_STX_WORD_AT(stx,assoc,ASE_STX_ASSOCIATION_VALUE);
meta = ASE_STX_CLASS(stx,value);
if (ASE_STX_CLASS(stx,meta) != stx->class_metaclass) return stx->nil;
return value;
}
int ase_stx_get_instance_variable_index (
ase_stx_t* stx, ase_word_t class_index,
const ase_char_t* name, ase_word_t* index)
{
ase_word_t index_super = 0;
ase_stx_class_t* class_obj;
ase_stx_char_object_t* string;
class_obj = (ase_stx_class_t*)ASE_STX_OBJECT(stx, class_index);
ase_assert (class_obj != ASE_NULL);
if (class_obj->superclass != stx->nil) {
if (ase_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 = ASE_STX_CHAR_OBJECT(stx, class_obj->variables);
if (ase_stx_strword(string->data, name, index) != ASE_NULL) {
*index += index_super;
return 0;
}
}
*index += index_super;
}
return -1;
}
ase_word_t ase_stx_lookup_class_variable (
ase_stx_t* stx, ase_word_t class_index, const ase_char_t* name)
{
ase_stx_class_t* class_obj;
class_obj = (ase_stx_class_t*)ASE_STX_OBJECT(stx, class_index);
ase_assert (class_obj != ASE_NULL);
if (class_obj->superclass != stx->nil) {
ase_word_t tmp;
tmp = ase_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 (ase_stx_dict_lookup(stx,
class_obj->class_variables,name) != stx->nil) return class_index;
}
return stx->nil;
}
ase_word_t ase_stx_lookup_method (ase_stx_t* stx,
ase_word_t class_index, const ase_char_t* name, ase_bool_t from_super)
{
ase_stx_class_t* class_obj;
class_obj = (ase_stx_class_t*)ASE_STX_OBJECT(stx, class_index);
ase_assert (class_obj != ASE_NULL);
#if 0
if (class_obj->header.class != stx->class_metaclass &&
class_obj->methods != stx->nil) {
ase_word_t assoc;
assoc = ase_stx_dict_lookup(stx, class_obj->methods, name);
if (assoc != stx->nil) {
ase_assert (ASE_STX_CLASS(stx,assoc) == stx->class_association);
return ASE_STX_WORD_AT(stx, assoc, ASE_STX_ASSOCIATION_VALUE);
}
}
if (class_obj->superclass != stx->nil) {
ase_word_t tmp;
tmp = ase_stx_lookup_method (
stx, class_obj->superclass, name);
if (tmp != stx->nil) return tmp;
}
#endif
while (class_index != stx->nil) {
class_obj = (ase_stx_class_t*)ASE_STX_OBJECT(stx, class_index);
ase_assert (class_obj != ASE_NULL);
ase_assert (
class_obj->header.class == stx->class_metaclass ||
ASE_STX_CLASS(stx,class_obj->header.class) == stx->class_metaclass);
if (from_super) {
from_super = ase_false;
}
else if (class_obj->methods != stx->nil) {
ase_word_t assoc;
assoc = ase_stx_dict_lookup(stx, class_obj->methods, name);
if (assoc != stx->nil) {
ase_assert (ASE_STX_CLASS(stx,assoc) == stx->class_association);
return ASE_STX_WORD_AT(stx, assoc, ASE_STX_ASSOCIATION_VALUE);
}
}
class_index = class_obj->superclass;
}
return stx->nil;
}

81
ase/stx/class.h Normal file
View File

@ -0,0 +1,81 @@
/*
* $Id: class.h,v 1.3 2007/04/30 08:32:40 bacon Exp $
*/
#ifndef _ASE_STX_CLASS_H_
#define _ASE_STX_CLASS_H_
#include <ase/stx/stx.h>
/* definitions for common objects */
#define ASE_STX_CLASS_SIZE 8
#define ASE_STX_CLASS_SPEC 0
#define ASE_STX_CLASS_METHODS 1
#define ASE_STX_CLASS_SUPERCLASS 2
#define ASE_STX_CLASS_SUBCLASSES 3
#define ASE_STX_CLASS_NAME 4
#define ASE_STX_CLASS_VARIABLES 5
#define ASE_STX_CLASS_CLASS_VARIABLES 6
#define ASE_STX_CLASS_POOL_DICTIONARIES 7
#define ASE_STX_METACLASS_SIZE 5
#define ASE_STX_METACLASS_SPEC 0
#define ASE_STX_METACLASS_METHODS 1
#define ASE_STX_METACLASS_SUPERCLASS 2
#define ASE_STX_METACLASS_SUBCLASSES 3
#define ASE_STX_METACLASS_INSTANCE_CLASS 4
#define ASE_STX_SPEC_INDEXABLE_BITS 2
#define ASE_STX_SPEC_INDEXABLE_MASK 3
#define ASE_STX_SPEC_NOT_INDEXABLE 0
#define ASE_STX_SPEC_WORD_INDEXABLE 1
#define ASE_STX_SPEC_BYTE_INDEXABLE 2
#define ASE_STX_SPEC_CHAR_INDEXABLE 3
struct ase_stx_class_t
{
ase_stx_objhdr_t header;
ase_word_t spec; /* indexable: 2, nfields: the rest */
ase_word_t methods;
ase_word_t superclass;
ase_word_t subclasses;
ase_word_t name;
ase_word_t variables;
ase_word_t class_variables;
ase_word_t pool_dictonaries;
};
struct ase_stx_metaclass_t
{
ase_stx_objhdr_t header;
ase_word_t spec;
ase_word_t methods;
ase_word_t superclass;
ase_word_t subclasses;
ase_word_t instance_class;
};
typedef struct ase_stx_class_t ase_stx_class_t;
typedef struct ase_stx_metaclass_t ase_stx_metaclass_t;
#ifdef __cplusplus
extern "C" {
#endif
ase_word_t ase_stx_new_class (ase_stx_t* stx, const ase_char_t* name);
ase_word_t ase_stx_lookup_class (ase_stx_t* stx, const ase_char_t* name);
int ase_stx_get_instance_variable_index (
ase_stx_t* stx, ase_word_t class_index,
const ase_char_t* name, ase_word_t* index);
ase_word_t ase_stx_lookup_class_variable (
ase_stx_t* stx, ase_word_t class_index, const ase_char_t* name);
ase_word_t ase_stx_lookup_method (ase_stx_t* stx,
ase_word_t class_index, const ase_char_t* name, ase_bool_t from_super);
#ifdef __cplusplus
}
#endif
#endif

75
ase/stx/context.c Normal file
View File

@ -0,0 +1,75 @@
/*
* $Id: context.c,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#include <ase/stx/context.h>
#include <ase/stx/object.h>
#include <ase/stx/class.h>
#include <ase/stx/misc.h>
ase_word_t ase_stx_new_context (ase_stx_t* stx,
ase_word_t method, ase_word_t args, ase_word_t temp)
{
ase_word_t context;
ase_stx_context_t* obj;
context = ase_stx_alloc_word_object(
stx, ASE_NULL, ASE_STX_CONTEXT_SIZE, ASE_NULL, 0);
obj = (ase_stx_context_t*)ASE_STX_OBJECT(stx,context);
obj->header.class = ase_stx_lookup_class(stx,ASE_T("Context"));
obj->ip = ASE_STX_TO_SMALLINT(0);
obj->method = method;
obj->arguments = args;
obj->temporaries = temp;
return context;
}
static ase_byte_t __fetch_byte (
ase_stx_t* stx, ase_stx_context_t* context_obj)
{
ase_word_t ip, method;
ase_assert (ASE_STX_IS_SMALLINT(context_obj->ip));
ip = ASE_STX_FROM_SMALLINT(context_obj->ip);
method = context_obj->method;
/* increment instruction pointer */
context_obj->ip = ASE_STX_TO_SMALLINT(ip + 1);
ase_assert (ASE_STX_TYPE(stx,method) == ASE_STX_BYTE_INDEXED);
return ASE_STX_BYTE_AT(stx,method,ip);
}
int ase_stx_run_context (ase_stx_t* stx, ase_word_t context)
{
ase_byte_t byte, operand;
ase_stx_context_t* context_obj;
context_obj = (ase_stx_context_t*)ASE_STX_OBJECT(stx,context);
while (!stx->__wantabort) {
/* check_process_switch (); // hopefully */
byte = __fetch_byte (stx, context_obj);
#ifdef _DOS
printf (ASE_T("code: %x\n"), byte);
#else
ase_printf (ASE_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
ase/stx/context.h Normal file
View File

@ -0,0 +1,43 @@
/*
* $Id: context.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_CONTEXT_H_
#define _ASE_STX_CONTEXT_H_
#include <ase/stx/stx.h>
#define PUSH_OBJECT 0xA0
#define SEND_UNARY_MESSAGE 0xB0
#define HALT 0xFF
#define ASE_STX_CONTEXT_SIZE 4
#define ASE_STX_CONTEXT_IP 0
#define ASE_STX_CONTEXT_METHOD 1
#define ASE_STX_CONTEXT_ARGUMENTS 2
#define ASE_STX_CONTEXT_TEMPORARIES 3
struct ase_stx_context_t
{
ase_stx_objhdr_t header;
ase_word_t ip;
ase_word_t method;
ase_word_t arguments;
ase_word_t temporaries;
};
typedef struct ase_stx_context_t ase_stx_context_t;
#ifdef __cplusplus
extern "C" {
#endif
ase_word_t ase_stx_new_context (ase_stx_t* stx,
ase_word_t method, ase_word_t args, ase_word_t temp);
int ase_stx_run_context (ase_stx_t* stx, ase_word_t context);
#ifdef __cplusplus
}
#endif
#endif

190
ase/stx/dict.c Normal file
View File

@ -0,0 +1,190 @@
/*
* $Id: dict.c,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#include <ase/stx/dict.h>
#include <ase/stx/object.h>
#include <ase/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.
*/
ase_word_t __new_association (
ase_stx_t* stx, ase_word_t key, ase_word_t value)
{
ase_word_t x;
#ifdef __GNUC__
ase_word_t data[2] = { key, value };
#else
ase_word_t data[2];
data[0] = key;
data[1] = value;
#endif
x = ase_stx_alloc_word_object (
stx, data, ASE_STX_ASSOCIATION_SIZE, ASE_NULL, 0);
ASE_STX_CLASS(stx,x) = stx->class_association;
return x;
}
static ase_word_t __dict_find_slot (
ase_stx_t* stx, ase_word_t dict, ase_word_t key)
{
ase_word_t size, hash, index, assoc, symbol;
ase_stx_word_object_t* dict_obj;
ase_assert (!ASE_STX_IS_SMALLINT(dict) &&
ASE_STX_IS_WORD_OBJECT(stx, dict));
ase_assert (dict == stx->smalltalk ||
ase_stx_classof(stx,dict) == stx->class_system_dictionary);
ase_assert (ase_stx_classof(stx,key) == stx->class_symbol);
size = ASE_STX_SIZE(stx,dict);
hash = ase_stx_hash_object(stx, key);
/* consider tally, the only instance variable of a system dictionary */
index = hash % (size - 1) + 1;
dict_obj = ASE_STX_WORD_OBJECT(stx,dict);
while (1) {
assoc = dict_obj->data[index];
if (assoc == stx->nil) break;
symbol = ASE_STX_WORD_AT(stx,assoc,ASE_STX_ASSOCIATION_KEY);
ase_assert (ase_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 (ase_strxncmp(
ASE_STX_DATA(stx,key), ASE_STX_SIZE(stx,key),
ASE_STX_DATA(stx,symbol), ASE_STX_SIZE(stx,symbol)) == 0) break;
/* consider tally here too */
index = index % (size - 1) + 1;
}
return index;
}
static void __grow_dict (ase_stx_t* stx, ase_word_t dict)
{
ase_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.
*/
ase_assert (stx->class_system_dictionary != stx->nil);
ase_assert (ase_stx_classof(stx,dict) == stx->class_system_dictionary);
size = ASE_STX_SIZE(stx,dict);
new = ase_stx_instantiate (stx,
ASE_STX_CLASS(stx,dict), ASE_NULL, ASE_NULL, (size - 1) * 2);
ASE_STX_WORD_AT(stx,new,0) = ASE_STX_TO_SMALLINT(0);
for (index = 1; index < size; index++) {
assoc = ASE_STX_WORD_AT(stx,dict,index);
if (assoc == stx->nil) continue;
ase_stx_dict_put (stx, new,
ASE_STX_WORD_AT(stx,assoc,ASE_STX_ASSOCIATION_KEY),
ASE_STX_WORD_AT(stx,assoc,ASE_STX_ASSOCIATION_VALUE));
}
/* TODO: explore if dict can be immediately destroyed. */
ase_assert (ase_sizeof(ase_stx_object_t*) == ase_sizeof(ase_uint_t));
ASE_SWAP (ASE_STX_OBJECT(stx,dict),
ASE_STX_OBJECT(stx,new),
ase_stx_object_t*, ase_uint_t);
}
ase_word_t ase_stx_dict_lookup (
ase_stx_t* stx, ase_word_t dict, const ase_char_t* key)
{
ase_word_t size, hash, index, assoc, symbol;
ase_stx_word_object_t* dict_obj;
ase_assert (!ASE_STX_IS_SMALLINT(dict) &&
ASE_STX_IS_WORD_OBJECT(stx, dict));
ase_assert (dict == stx->smalltalk ||
ase_stx_classof(stx,dict) == stx->class_system_dictionary);
size = ASE_STX_SIZE(stx,dict);
hash = ase_stx_hash(key, ase_strlen(key) * ase_sizeof(ase_char_t));
/* consider tally, the only instance variable of a system dictionary */
index = hash % (size - 1) + 1;
dict_obj = ASE_STX_WORD_OBJECT(stx,dict);
while (1) {
assoc = dict_obj->data[index];
if (assoc == stx->nil) break;
symbol = ASE_STX_WORD_AT(stx,assoc,ASE_STX_ASSOCIATION_KEY);
ase_assert (ase_stx_classof(stx,symbol) == stx->class_symbol);
if (ase_strxcmp (ASE_STX_DATA(stx,symbol),
ASE_STX_SIZE(stx,symbol), key) == 0) break;
/* consider tally here too */
index = index % (size - 1) + 1;
}
return ASE_STX_WORD_AT(stx,dict,index);
}
ase_word_t ase_stx_dict_get (ase_stx_t* stx, ase_word_t dict, ase_word_t key)
{
return ASE_STX_WORD_AT(stx,dict,__dict_find_slot(stx, dict, key));
}
ase_word_t ase_stx_dict_put (
ase_stx_t* stx, ase_word_t dict, ase_word_t key, ase_word_t value)
{
ase_word_t slot, capa, tally, assoc;
/* the dictionary must have at least one slot excluding tally */
ase_assert (ASE_STX_SIZE(stx,dict) > 1);
capa = ASE_STX_SIZE(stx,dict) - 1;
tally = ASE_STX_FROM_SMALLINT(ASE_STX_WORD_AT(stx,dict,0));
if (capa <= tally + 1) {
__grow_dict (stx, dict);
/* refresh tally */
tally = ASE_STX_FROM_SMALLINT(ASE_STX_WORD_AT(stx,dict,0));
}
slot = __dict_find_slot (stx, dict, key);
assoc = ASE_STX_WORD_AT(stx,dict,slot);
if (assoc == stx->nil) {
ASE_STX_WORD_AT(stx,dict,slot) =
__new_association (stx, key, value);
ASE_STX_WORD_AT(stx,dict,0) = ASE_STX_TO_SMALLINT(tally + 1);
}
else ASE_STX_WORD_AT(stx,assoc,ASE_STX_ASSOCIATION_VALUE) = value;
return ASE_STX_WORD_AT(stx,dict,slot);
}
void ase_stx_dict_traverse (
ase_stx_t* stx, ase_word_t dict,
void (*func) (ase_stx_t*,ase_word_t,void*), void* data)
{
ase_word_t index, assoc;
ase_word_t size = ASE_STX_SIZE(stx,dict);
for (index = 1; index < size; index++) {
assoc = ASE_STX_WORD_AT(stx,dict,index);
if (assoc == stx->nil) continue;
func (stx, assoc, data);
}
}

42
ase/stx/dict.h Normal file
View File

@ -0,0 +1,42 @@
/*
* $Id: dict.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_DICT_H_
#define _ASE_STX_DICT_H_
#include <ase/stx/stx.h>
#define ASE_STX_ASSOCIATION_SIZE 2
#define ASE_STX_ASSOCIATION_KEY 0
#define ASE_STX_ASSOCIATION_VALUE 1
struct ase_stx_association_t
{
ase_stx_objhdr_t header;
ase_word_t key;
ase_word_t value;
};
typedef struct ase_stx_association_t ase_stx_association_t;
#ifdef __cplusplus
extern "C"
#endif
ase_word_t ase_stx_dict_lookup (
ase_stx_t* stx, ase_word_t dict, const ase_char_t* key);
ase_word_t ase_stx_dict_get (
ase_stx_t* stx, ase_word_t dict, ase_word_t key);
ase_word_t ase_stx_dict_put (
ase_stx_t* stx, ase_word_t dict, ase_word_t key, ase_word_t value);
void ase_stx_dict_traverse (
ase_stx_t* stx, ase_word_t dict,
void (*func) (ase_stx_t*,ase_word_t,void*), void* data);
#ifdef __cplusplus
}
#endif
#endif

380
ase/stx/interp.c Normal file
View File

@ -0,0 +1,380 @@
/*
* $Id: interp.c,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#include <ase/stx/interp.h>
#include <ase/stx/method.h>
#include <ase/stx/object.h>
#include <ase/stx/array.h>
#include <ase/stx/class.h>
#include <ase/bas/assert.h>
#include <ase/bas/memory.h>
/*
activation record
....
....
....
-------------------
previous stack_base
-------------------
method
-------------------
pc
-------------------
temporaries
-------------------
arguments
-------------------
receiver
------------------- <----- current stack_base
....
....
....
*/
struct process_t
{
ase_word_t* stack;
ase_word_t stack_size;
ase_word_t stack_base;
ase_word_t stack_top;
ase_word_t receiver;
ase_word_t method;
ase_word_t pc;
/* cached information about the method above */
ase_word_t* literals;
ase_byte_t* bytecodes;
ase_word_t bytecode_size;
ase_size_t argcount;
ase_size_t tmpcount;
};
typedef struct process_t process_t;
static int __run_process (ase_stx_t* stx, process_t* proc);
static int __push_to_stack (ase_stx_t* stx,
process_t* proc, ase_word_t what, ase_word_t index);
static int __store_from_stack (ase_stx_t* stx,
process_t* proc, ase_word_t what, ase_word_t index);
static int __send_message (ase_stx_t* stx, process_t* proc,
ase_word_t nargs, ase_word_t selector, ase_bool_t to_super);
static int __return_from_message (ase_stx_t* stx, process_t* proc);
static int __dispatch_primitive (ase_stx_t* stx, process_t* proc, ase_word_t no);
int ase_stx_interp (ase_stx_t* stx, ase_word_t receiver, ase_word_t method)
{
process_t proc;
ase_stx_method_t* mthobj;
ase_word_t i;
int n;
// TODO: size of process stack.
proc.stack = (ase_word_t*)ase_malloc (10000 * ase_sizeof(ase_word_t));
if (proc.stack == ASE_NULL) {
ase_printf (ASE_T("out of memory in ase_stx_interp\n"));
return -1;
}
proc.stack_size = 10000;
proc.stack_base = 0;
proc.stack_top = 0;
mthobj = (ase_stx_method_t*)ASE_STX_OBJECT(stx,method);
ase_assert (mthobj != ASE_NULL);
proc.literals = mthobj->literals;
proc.bytecodes = ASE_STX_DATA(stx, mthobj->bytecodes);
proc.bytecode_size = ASE_STX_SIZE(stx, mthobj->bytecodes);
/* TODO: disable the method with arguments for start-up */
proc.argcount = ASE_STX_FROM_SMALLINT(mthobj->argcount);
proc.tmpcount = ASE_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);
ase_free (proc.stack);
return n;
}
static int __run_process (ase_stx_t* stx, process_t* proc)
{
int code, next, next2;
while (proc->pc < proc->bytecode_size) {
code = proc->bytecodes[proc->pc++];
#ifdef DEBUG
ase_printf (ASE_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], ase_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], ase_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], ase_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], ase_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 {
ase_printf (ASE_T("INVALID OPCODE...........\n"));
break;
}
}
return 0;
}
static int __push_to_stack (ase_stx_t* stx,
process_t* proc, ase_word_t what, ase_word_t index)
{
switch (what) {
case 0: /* receiver variable */
proc->stack[proc->stack_top++] =
ASE_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 (ase_stx_t* stx,
process_t* proc, ase_word_t what, ase_word_t index)
{
switch (what) {
case 4: /* receiver variable */
ASE_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 (ase_stx_t* stx, process_t* proc,
ase_word_t nargs, ase_word_t selector, ase_bool_t to_super)
{
ase_word_t receiver, method;
ase_word_t i, tmpcount, argcount;
ase_stx_method_t* mthobj;
ase_assert (ASE_STX_CLASS(stx,selector) == stx->class_symbol);
receiver = proc->stack[proc->stack_top - nargs - 1];
method = ase_stx_lookup_method (
stx, ASE_STX_CLASS(stx,receiver),
ASE_STX_DATA(stx,selector), to_super);
if (method == stx->nil) {
ase_printf (ASE_T("cannot find the method....\n"));
return -1;
}
mthobj = (ase_stx_method_t*)ASE_STX_OBJECT(stx,method);
argcount = ASE_STX_FROM_SMALLINT(mthobj->argcount);
tmpcount = ASE_STX_FROM_SMALLINT(mthobj->tmpcount);
ase_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;
ase_assert (proc->stack_base > 0);
proc->receiver = receiver;
proc->method = method;
proc->pc = 0;
proc->literals = mthobj->literals;
proc->bytecodes = ASE_STX_DATA(stx, mthobj->bytecodes);
proc->bytecode_size = ASE_STX_SIZE(stx, mthobj->bytecodes);
proc->argcount = argcount;
proc->tmpcount = tmpcount;
return 0;
}
static int __return_from_message (ase_stx_t* stx, process_t* proc)
{
ase_word_t method, pc, stack_base;
ase_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 = (ase_stx_method_t*)ASE_STX_OBJECT(stx,method);
ase_assert (mthobj != ASE_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 = ASE_STX_DATA(stx, mthobj->bytecodes);
proc->bytecode_size = ASE_STX_SIZE(stx, mthobj->bytecodes);
proc->argcount = ASE_STX_FROM_SMALLINT(mthobj->argcount);
proc->tmpcount = ASE_STX_FROM_SMALLINT(mthobj->tmpcount);
return 0;
}
static int __dispatch_primitive (ase_stx_t* stx, process_t* proc, ase_word_t no)
{
switch (no) {
case 0:
ase_printf (ASE_T("[[ hello stx smalltalk ]]\n"));
break;
case 1:
ase_printf (ASE_T("<< AMAZING STX SMALLTALK WORLD >>\n"));
break;
case 2:
ase_printf (ASE_T("<< FUNKY STX SMALLTALK >> %d\n"),
ASE_STX_FROM_SMALLINT(proc->stack[proc->stack_base + 1]));
break;
case 3:
ase_printf (ASE_T("<< HIGH STX SMALLTALK >> %d, %d\n"),
ASE_STX_FROM_SMALLINT(proc->stack[proc->stack_base + 1]),
ASE_STX_FROM_SMALLINT(proc->stack[proc->stack_base + 2]));
break;
case 20:
ase_printf (ASE_T("<< PRIMITIVE 20 >>\n"));
break;
}
return 0;
}

20
ase/stx/interp.h Normal file
View File

@ -0,0 +1,20 @@
/*
* $Id: interp.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_INTERP_H_
#define _ASE_STX_INTERP_H_
#include <ase/stx/stx.h>
#ifdef __cplusplus
extern "C" {
#endif
int ase_stx_interp (ase_stx_t* stx, ase_word_t receiver, ase_word_t method);
#ifdef __cplusplus
}
#endif
#endif

21
ase/stx/makefile.bcc Normal file
View File

@ -0,0 +1,21 @@
SRCS = stx.c memory.c object.c symbol.c class.c dict.c misc.c array.c \
name.c token.c parser.c bootstrp.c bytecode.c interp.c
OBJS = $(SRCS:.c=.obj)
OUT = xpstx.lib
CC = bcc32
CFLAGS = -O2 -WM -w -w-inl -w-sig -w-spa -w-hid -RT- -I../..
all: $(OBJS)
tlib $(OUT) @&&!
+-$(**: = &^
+-)
!
clean:
del $(OBJS) $(OUT) *.obj
.SUFFIXES: .c .obj
.c.obj:
$(CC) $(CFLAGS) -c $<

23
ase/stx/makefile.cl Normal file
View File

@ -0,0 +1,23 @@
SRCS = \
stx.c memory.c object.c symbol.c class.c array.c \
dict.c misc.c name.c token.c parser.c bootstrp.c \
bytecode.c interp.c
OBJS = $(SRCS:.c=.obj)
OUT = xpstx.lib
CC = cl
CFLAGS = /nologo /MT /GX /W3 /GR- -I../..
all: $(OBJS)
link -lib @<<
/nologo /out:$(OUT) $(OBJS)
<<
clean:
del $(OBJS) $(OUT) *.obj
.SUFFIXES: .c .obj
.c.obj:
$(CC) $(CFLAGS) /c $<

28
ase/stx/makefile.in Normal file
View File

@ -0,0 +1,28 @@
OUT = asestx
C_SRCS = stx.c memory.c object.c symbol.c class.c array.c \
dict.c misc.c context.c name.c token.c parser.c bootstrp.c \
bytecode.c interp.c
C_OBJS = $(C_SRCS:.c=.o)
CC = @CC@
AR = ar
RANLIB = @RANLIB@
CFLAGS = @CFLAGS@ -I@abs_top_builddir@/..
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
all: lib
lib: $(C_OBJS)
$(AR) cr lib$(OUT).a $(C_OBJS)
if [ "$(RANLIB)" = "ranlib" ]; then ranlib lib$(OUT).a; fi
clean:
rm -rf $(OBJS) lib$(OUT).a *.o
.SUFFIXES: .c .o
.c.o:
$(CC) $(CFLAGS) -c $<

22
ase/stx/makefile.lcc Normal file
View File

@ -0,0 +1,22 @@
SRCS = stx.c memory.c object.c symbol.c class.c array.c \
dict.c misc.c name.c token.c parser.c bootstrp.c \
bytecode.c interp.c
OBJS = stx.obj memory.obj object.obj symbol.obj class.obj array.obj \
dict.obj misc.obj name.obj token.obj parser.obj bootstrp.obj \
bytecode.obj interp.obj
OUT = xpstx.lib
CC = lcc
CFLAGS = -I../.. -A -ansic #-libcdll
LDFLAGS =
LIBS =
all: $(OBJS)
lcclib $(OUT) $(OBJS)
clean:
del $(OBJS) $(OUT) *.obj
.SUFFIXES: .c .obj
.c.obj:
$(CC) $(CFLAGS) -c $<

22
ase/stx/makefile.tcc Normal file
View File

@ -0,0 +1,22 @@
SRCS = \
stx.c memory.c object.c symbol.c dict.c misc.c context.c
OBJS = $(SRCS:.c=.obj)
OUT = xpstx.lib
TC = \dos\tcc
CC = $(TC)\tcc
CFLAGS = -I..\.. -D_DOS -ml -w
all: $(OBJS)
$(TC)\tlib $(OUT) @&&!
+-$(**: = &^
+-)
!
clean:
del $(OBJS) $(OUT) *.obj
.SUFFIXES: .c .obj
.c.obj:
$(CC) $(CFLAGS) -c $<

98
ase/stx/memory.c Normal file
View File

@ -0,0 +1,98 @@
/*
* $Id: memory.c,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#include <ase/stx/memory.h>
#include <ase/stx/misc.h>
ase_stx_memory_t* ase_stx_memory_open (
ase_stx_memory_t* mem, ase_word_t capacity)
{
ase_stx_object_t** slots;
ase_word_t n;
ase_assert (capacity > 0);
if (mem == ASE_NULL) {
mem = (ase_stx_memory_t*)ase_malloc(ase_sizeof(ase_stx_memory_t));
if (mem == ASE_NULL) return ASE_NULL;
mem->__dynamic = ase_true;
}
else mem->__dynamic = ase_false;
slots = (ase_stx_object_t**)ase_malloc (
capacity * ase_sizeof(ase_stx_object_t*));
if (slots == ASE_NULL) {
if (mem->__dynamic) ase_free (mem);
mem = ASE_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] = (ase_stx_object_t*)&mem->slots[n + 1];
}
mem->slots[n] = ASE_NULL;
return mem;
}
void ase_stx_memory_close (ase_stx_memory_t* mem)
{
/* TODO: free all linked objects... */
ase_free (mem->slots);
mem->capacity = 0;
mem->slots = ASE_NULL;
mem->free = ASE_NULL;
if (mem->__dynamic) ase_free (mem);
}
void ase_stx_memory_gc (ase_stx_memory_t* mem)
{
/* TODO: implement this function */
}
ase_word_t ase_stx_memory_alloc (ase_stx_memory_t* mem, ase_word_t nbytes)
{
ase_stx_object_t** slot;
ase_stx_object_t* object;
/* find the free object slot */
if (mem->free == ASE_NULL) {
ase_stx_memory_gc (mem);
if (mem->free == ASE_NULL) return mem->capacity;;
}
object = (ase_stx_object_t*)ase_malloc (nbytes);
if (object == ASE_NULL) {
ase_stx_memory_gc (mem);
object = (ase_stx_object_t*)ase_malloc (nbytes);
/*if (object == ASE_NULL) return mem->capacity;*/
if (object == ASE_NULL) {
ase_assert (ASE_T("MEMORY ALLOCATION ERROR\n") == ASE_NULL);
exit (1);
}
}
slot = mem->free;
mem->free = (ase_stx_object_t**)*slot;
*slot = object;
return (ase_word_t)(slot - mem->slots);
}
void ase_stx_memory_dealloc (ase_stx_memory_t* mem, ase_word_t object_index)
{
/*
* THIS IS PRIMITIVE LOW-LEVEL DEALLOC. THIS WILL NOT
* DEALLOCATE MEMORY ALLOCATED FOR ITS INSTANCE VARIABLES.
*/
ase_free (mem->slots[object_index]);
mem->slots[object_index] = (ase_stx_object_t*)mem->free;
mem->free = &mem->slots[object_index];
}

26
ase/stx/memory.h Normal file
View File

@ -0,0 +1,26 @@
/*
* $Id: memory.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_MEMORY_H_
#define _ASE_STX_MEMORY_H_
#include <ase/stx/stx.h>
#ifdef __cplusplus
extern "C" {
#endif
ase_stx_memory_t* ase_stx_memory_open (
ase_stx_memory_t* mem, ase_word_t capacity);
void ase_stx_memory_close (ase_stx_memory_t* mem);
void ase_stx_memory_gc (ase_stx_memory_t* mem);
ase_word_t ase_stx_memory_alloc (ase_stx_memory_t* mem, ase_word_t size);
void ase_stx_memory_dealloc (ase_stx_memory_t* mem, ase_word_t object_index);
#ifdef __cplusplus
}
#endif
#endif

50
ase/stx/method.h Normal file
View File

@ -0,0 +1,50 @@
/*
* $Id: method.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_METHOD_H_
#define _ASE_STX_METHOD_H_
#include <ase/stx/stx.h>
#define ASE_STX_METHOD_SIZE 5
#define ASE_STX_METHOD_TEXT 0
#define ASE_STX_METHOD_SELECTOR 1
#define ASE_STX_METHOD_BYTECODES 2
#define ASE_STX_METHOD_TMPCOUNT 3
#define ASE_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 ase_stx_method_t
{
ase_stx_objhdr_t header;
ase_word_t text;
ase_word_t selector; /* is this necessary? */
ase_word_t bytecodes;
ase_word_t tmpcount;
ase_word_t argcount;
ase_word_t literals[1];
};
typedef struct ase_stx_method_t ase_stx_method_t;
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

70
ase/stx/misc.c Normal file
View File

@ -0,0 +1,70 @@
/*
* $Id: misc.c,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#include <ase/stx/misc.h>
ase_word_t ase_stx_hash (const void* data, ase_word_t len)
{
ase_word_t h = 0;
ase_byte_t* bp, * be;
bp = (ase_byte_t*)data; be = bp + len;
while (bp < be) h = h * 31 + *bp++;
return h;
}
ase_word_t ase_stx_strhash (const ase_char_t* str)
{
ase_word_t h = 0;
ase_byte_t* bp, * be;
const ase_char_t* p = str;
while (*p != ASE_T('\0')) {
bp = (ase_byte_t*)p;
be = bp + ase_sizeof(ase_char_t);
while (bp < be) h = h * 31 + *bp++;
p++;
}
return h;
}
ase_word_t ase_stx_strxhash (const ase_char_t* str, ase_word_t len)
{
ase_word_t h = 0;
ase_byte_t* bp, * be;
const ase_char_t* p = str, * end = str + len;
while (p < end) {
bp = (ase_byte_t*)p;
be = bp + ase_sizeof(ase_char_t);
while (bp < be) h = h * 31 + *bp++;
p++;
}
return h;
}
ase_char_t* ase_stx_strword (
const ase_char_t* str, const ase_char_t* word, ase_word_t* word_index)
{
ase_char_t* p = (ase_char_t*)str;
ase_char_t* tok;
ase_size_t len;
ase_word_t index = 0;
while (p != ASE_NULL) {
p = ase_strtok (p, ASE_T(""), &tok, &len);
if (ase_strxcmp (tok, len, word) == 0) {
*word_index = index;
return tok;
}
index++;
}
*word_index = index;
return ASE_NULL;
}

63
ase/stx/misc.h Normal file
View File

@ -0,0 +1,63 @@
/*
* $Id: misc.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_MISC_H_
#define _ASE_STX_MISC_H_
#include <ase/stx/stx.h>
/* TODO: remove this header later */
#include <ase/bas/stdio.h>
#ifdef _DOS
#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define ase_assert assert
#define ase_malloc malloc
#define ase_realloc realloc
#define ase_free free
#define ase_va_list va_list
#define ase_va_start va_start
#define ase_va_end va_end
#define ase_va_arg va_arg
#define ase_isspace isspace
#define ase_isdigit isdigit
#define ase_isalpha isalpha
#define ase_isalnum isalnum
#else
#include <ase/bas/memory.h>
#include <ase/bas/assert.h>
#include <ase/bas/stdarg.h>
#include <ase/bas/ctype.h>
#include <ase/bas/string.h>
#include <ase/bas/stdlib.h>
#endif
#if defined(__BORLANDC__) || defined(_MSC_VER)
#define INLINE
#else
#define INLINE inline
#endif
#ifdef __cplusplus
extern "C" {
#endif
ase_word_t ase_stx_hash (const void* data, ase_word_t len);
ase_word_t ase_stx_strhash (const ase_char_t* str);
ase_word_t ase_stx_strxhash (const ase_char_t* str, ase_word_t len);
ase_char_t* ase_stx_strword (
const ase_char_t* str, const ase_char_t* word, ase_word_t* word_index);
#ifdef __cplusplus
}
#endif
#endif

146
ase/stx/name.c Normal file
View File

@ -0,0 +1,146 @@
/*
* $Id: name.c,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#include <ase/stx/name.h>
#include <ase/stx/misc.h>
ase_stx_name_t* ase_stx_name_open (
ase_stx_name_t* name, ase_word_t capacity)
{
if (capacity == 0)
capacity = ase_countof(name->static_buffer) - 1;
if (name == ASE_NULL) {
name = (ase_stx_name_t*)
ase_malloc (ase_sizeof(ase_stx_name_t));
if (name == ASE_NULL) return ASE_NULL;
name->__dynamic = ase_true;
}
else name->__dynamic = ase_false;
if (capacity < ase_countof(name->static_buffer)) {
name->buffer = name->static_buffer;
}
else {
name->buffer = (ase_char_t*)
ase_malloc ((capacity + 1) * ase_sizeof(ase_char_t));
if (name->buffer == ASE_NULL) {
if (name->__dynamic) ase_free (name);
return ASE_NULL;
}
}
name->size = 0;
name->capacity = capacity;
name->buffer[0] = ASE_T('\0');
return name;
}
void ase_stx_name_close (ase_stx_name_t* name)
{
if (name->capacity >= ase_countof(name->static_buffer)) {
ase_assert (name->buffer != name->static_buffer);
ase_free (name->buffer);
}
if (name->__dynamic) ase_free (name);
}
int ase_stx_name_addc (ase_stx_name_t* name, ase_cint_t c)
{
if (name->size >= name->capacity) {
/* double the capacity. */
ase_size_t new_capacity = name->capacity * 2;
if (new_capacity >= ase_countof(name->static_buffer)) {
ase_char_t* space;
if (name->capacity < ase_countof(name->static_buffer)) {
space = (ase_char_t*)ase_malloc (
(new_capacity + 1) * ase_sizeof(ase_char_t));
if (space == ASE_NULL) return -1;
/* don't need to copy up to the terminating null */
ase_memcpy (space, name->buffer,
name->capacity * ase_sizeof(ase_char_t));
}
else {
space = (ase_char_t*)ase_realloc (name->buffer,
(new_capacity + 1) * ase_sizeof(ase_char_t));
if (space == ASE_NULL) return -1;
}
name->buffer = space;
}
name->capacity = new_capacity;
}
name->buffer[name->size++] = c;
name->buffer[name->size] = ASE_T('\0');
return 0;
}
int ase_stx_name_adds (ase_stx_name_t* name, const ase_char_t* s)
{
while (*s != ASE_T('\0')) {
if (ase_stx_name_addc(name, *s) == -1) return -1;
s++;
}
return 0;
}
void ase_stx_name_clear (ase_stx_name_t* name)
{
name->size = 0;
name->buffer[0] = ASE_T('\0');
}
ase_char_t* ase_stx_name_yield (ase_stx_name_t* name, ase_word_t capacity)
{
ase_char_t* old_buffer, * new_buffer;
if (capacity == 0)
capacity = ase_countof(name->static_buffer) - 1;
if (name->capacity < ase_countof(name->static_buffer)) {
old_buffer = (ase_char_t*)
ase_malloc((name->capacity + 1) * ase_sizeof(ase_char_t));
if (old_buffer == ASE_NULL) return ASE_NULL;
ase_memcpy (old_buffer, name->buffer,
(name->capacity + 1) * ase_sizeof(ase_char_t));
}
else old_buffer = name->buffer;
if (capacity < ase_countof(name->static_buffer)) {
new_buffer = name->static_buffer;
}
else {
new_buffer = (ase_char_t*)
ase_malloc((capacity + 1) * ase_sizeof(ase_char_t));
if (new_buffer == ASE_NULL) return ASE_NULL;
}
name->buffer = new_buffer;
name->size = 0;
name->capacity = capacity;
name->buffer[0] = ASE_T('\0');
return old_buffer;
}
int ase_stx_name_compare (ase_stx_name_t* name, const ase_char_t* str)
{
ase_char_t* p = name->buffer;
ase_word_t index = 0;
while (index < name->size) {
if (*p > *str) return 1;
if (*p < *str) return -1;
index++; p++; str++;
}
return (*str == ASE_T('\0'))? 0: -1;
}

39
ase/stx/name.h Normal file
View File

@ -0,0 +1,39 @@
/*
* $Id: name.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_NAME_H_
#define _ASE_STX_NAME_H_
#include <ase/stx/stx.h>
struct ase_stx_name_t
{
ase_word_t capacity;
ase_word_t size;
ase_char_t* buffer;
ase_char_t static_buffer[128];
ase_bool_t __dynamic;
};
typedef struct ase_stx_name_t ase_stx_name_t;
#ifdef __cplusplus
extern "C" {
#endif
ase_stx_name_t* ase_stx_name_open (
ase_stx_name_t* name, ase_word_t capacity);
void ase_stx_name_close (ase_stx_name_t* name);
int ase_stx_name_addc (ase_stx_name_t* name, ase_cint_t c);
int ase_stx_name_adds (ase_stx_name_t* name, const ase_char_t* s);
void ase_stx_name_clear (ase_stx_name_t* name);
ase_char_t* ase_stx_name_yield (ase_stx_name_t* name, ase_word_t capacity);
int ase_stx_name_compare (ase_stx_name_t* name, const ase_char_t* str);
#ifdef __cplusplus
}
#endif
#endif

246
ase/stx/object.c Normal file
View File

@ -0,0 +1,246 @@
/*
* $Id: object.c,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#include <ase/stx/object.h>
#include <ase/stx/memory.h>
#include <ase/stx/symbol.h>
#include <ase/stx/class.h>
#include <ase/stx/misc.h>
/* n: number of instance variables */
ase_word_t ase_stx_alloc_word_object (
ase_stx_t* stx, const ase_word_t* data, ase_word_t nfields,
const ase_word_t* variable_data, ase_word_t variable_nfields)
{
ase_word_t idx, n;
ase_stx_word_object_t* obj;
ase_assert (stx->nil == ASE_STX_NIL);
/* bytes to allocated =
* (number of instance variables +
* number of variable instance variables) * word_size
*/
n = nfields + variable_nfields;
idx = ase_stx_memory_alloc (&stx->memory,
n * ase_sizeof(ase_word_t) + ase_sizeof(ase_stx_object_t));
if (idx >= stx->memory.capacity) return idx; /* failed TODO: return a difference value OINDEX_INVALID */
idx = ASE_STX_TO_OINDEX(idx);
obj = ASE_STX_WORD_OBJECT(stx,idx);
obj->header.class = stx->nil;
obj->header.access = (n << 2) | ASE_STX_WORD_INDEXED;
if (variable_data == ASE_NULL) {
while (n > nfields) obj->data[--n] = stx->nil;
}
else {
while (n > nfields) {
n--; obj->data[n] = variable_data[n - nfields];
}
}
if (data == ASE_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 */
ase_word_t ase_stx_alloc_byte_object (
ase_stx_t* stx, const ase_byte_t* data, ase_word_t n)
{
ase_word_t idx;
ase_stx_byte_object_t* obj;
ase_assert (stx->nil == ASE_STX_NIL);
idx = ase_stx_memory_alloc (
&stx->memory, n + ase_sizeof(ase_stx_object_t));
if (idx >= stx->memory.capacity) return idx; /* failed */
idx = ASE_STX_TO_OINDEX(idx);
obj = ASE_STX_BYTE_OBJECT(stx,idx);
obj->header.class = stx->nil;
obj->header.access = (n << 2) | ASE_STX_BYTE_INDEXED;
if (data == ASE_NULL) {
while (n-- > 0) obj->data[n] = 0;
}
else {
while (n-- > 0) obj->data[n] = data[n];
}
return idx;
}
ase_word_t ase_stx_alloc_char_object (
ase_stx_t* stx, const ase_char_t* str)
{
return (str == ASE_NULL)?
ase_stx_alloc_char_objectx (stx, ASE_NULL, 0):
ase_stx_alloc_char_objectx (stx, str, ase_strlen(str));
}
/* n: number of characters */
ase_word_t ase_stx_alloc_char_objectx (
ase_stx_t* stx, const ase_char_t* str, ase_word_t n)
{
ase_word_t idx;
ase_stx_char_object_t* obj;
ase_assert (stx->nil == ASE_STX_NIL);
idx = ase_stx_memory_alloc (&stx->memory,
(n + 1) * ase_sizeof(ase_char_t) + ase_sizeof(ase_stx_object_t));
if (idx >= stx->memory.capacity) return idx; /* failed */
idx = ASE_STX_TO_OINDEX(idx);
obj = ASE_STX_CHAR_OBJECT(stx,idx);
obj->header.class = stx->nil;
obj->header.access = (n << 2) | ASE_STX_CHAR_INDEXED;
obj->data[n] = ASE_T('\0');
if (str == ASE_NULL) {
while (n-- > 0) obj->data[n] = ASE_T('\0');
}
else {
while (n-- > 0) obj->data[n] = str[n];
}
return idx;
}
ase_word_t ase_stx_allocn_char_object (ase_stx_t* stx, ...)
{
ase_word_t idx, n = 0;
const ase_char_t* p;
ase_va_list ap;
ase_stx_char_object_t* obj;
ase_assert (stx->nil == ASE_STX_NIL);
ase_va_start (ap, stx);
while ((p = ase_va_arg(ap, const ase_char_t*)) != ASE_NULL) {
n += ase_strlen(p);
}
ase_va_end (ap);
idx = ase_stx_memory_alloc (&stx->memory,
(n + 1) * ase_sizeof(ase_char_t) + ase_sizeof(ase_stx_object_t));
if (idx >= stx->memory.capacity) return idx; /* failed */
idx = ASE_STX_TO_OINDEX(idx);
obj = ASE_STX_CHAR_OBJECT(stx,idx);
obj->header.class = stx->nil;
obj->header.access = (n << 2) | ASE_STX_CHAR_INDEXED;
obj->data[n] = ASE_T('\0');
ase_va_start (ap, stx);
n = 0;
while ((p = ase_va_arg(ap, const ase_char_t*)) != ASE_NULL) {
while (*p != ASE_T('\0')) {
/*ASE_STX_CHAR_AT(stx,idx,n++) = *p++;*/
obj->data[n++] = *p++;
}
}
ase_va_end (ap);
return idx;
}
ase_word_t ase_stx_hash_object (ase_stx_t* stx, ase_word_t object)
{
ase_word_t hv;
if (ASE_STX_IS_SMALLINT(object)) {
ase_word_t tmp = ASE_STX_FROM_SMALLINT(object);
hv = ase_stx_hash(&tmp, ase_sizeof(tmp));
}
else if (ASE_STX_IS_CHAR_OBJECT(stx,object)) {
/* the additional null is not taken into account */
hv = ase_stx_hash (ASE_STX_DATA(stx,object),
ASE_STX_SIZE(stx,object) * ase_sizeof(ase_char_t));
}
else if (ASE_STX_IS_BYTE_OBJECT(stx,object)) {
hv = ase_stx_hash (
ASE_STX_DATA(stx,object), ASE_STX_SIZE(stx,object));
}
else {
ase_assert (ASE_STX_IS_WORD_OBJECT(stx,object));
hv = ase_stx_hash (ASE_STX_DATA(stx,object),
ASE_STX_SIZE(stx,object) * ase_sizeof(ase_word_t));
}
return hv;
}
ase_word_t ase_stx_instantiate (
ase_stx_t* stx, ase_word_t class, const void* data,
const void* variable_data, ase_word_t variable_nfields)
{
ase_stx_class_t* class_obj;
ase_word_t spec, nfields, new;
int indexable;
ase_assert (class != stx->class_smallinteger);
class_obj = (ase_stx_class_t*)ASE_STX_OBJECT(stx, class);
/* don't instantiate a metaclass whose instance must be
created in a different way */
/* TODO: maybe delete the following line */
ase_assert (class_obj->header.class != stx->class_metaclass);
ase_assert (ASE_STX_IS_SMALLINT(class_obj->spec));
spec = ASE_STX_FROM_SMALLINT(class_obj->spec);
nfields = (spec >> ASE_STX_SPEC_INDEXABLE_BITS);
indexable = spec & ASE_STX_SPEC_INDEXABLE_MASK;
if (indexable == ASE_STX_SPEC_BYTE_INDEXABLE) {
ase_assert (nfields == 0 && data == ASE_NULL);
new = ase_stx_alloc_byte_object(
stx, variable_data, variable_nfields);
}
else if (indexable == ASE_STX_SPEC_CHAR_INDEXABLE) {
ase_assert (nfields == 0 && data == ASE_NULL);
new = ase_stx_alloc_char_objectx(
stx, variable_data, variable_nfields);
}
else if (indexable == ASE_STX_SPEC_WORD_INDEXABLE) {
new = ase_stx_alloc_word_object (
stx, data, nfields, variable_data, variable_nfields);
}
else {
ase_assert (indexable == ASE_STX_SPEC_NOT_INDEXABLE);
ase_assert (variable_nfields == 0 && variable_data == ASE_NULL);
new = ase_stx_alloc_word_object (
stx, data, nfields, ASE_NULL, 0);
}
ASE_STX_CLASS(stx, new) = class;
return new;
}
ase_word_t ase_stx_class (ase_stx_t* stx, ase_word_t obj)
{
return ASE_STX_IS_SMALLINT(obj)?
stx->class_smallinteger: ASE_STX_CLASS(stx,obj);
}
ase_word_t ase_stx_classof (ase_stx_t* stx, ase_word_t obj)
{
return ASE_STX_IS_SMALLINT(obj)?
stx->class_smallinteger: ASE_STX_CLASS(stx,obj);
}
ase_word_t ase_stx_sizeof (ase_stx_t* stx, ase_word_t obj)
{
return ASE_STX_IS_SMALLINT(obj)? 1: ASE_STX_SIZE(stx,obj);
}

40
ase/stx/object.h Normal file
View File

@ -0,0 +1,40 @@
/*
* $Id: object.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_OBJECT_H_
#define _ASE_STX_OBJECT_H_
#include <ase/stx/stx.h>
#ifdef __cplusplus
extern "C" {
#endif
ase_word_t ase_stx_alloc_word_object (
ase_stx_t* stx, const ase_word_t* data, ase_word_t nfields,
const ase_word_t* variable_data, ase_word_t variable_nfields);
ase_word_t ase_stx_alloc_byte_object (
ase_stx_t* stx, const ase_byte_t* data, ase_word_t n);
ase_word_t ase_stx_alloc_char_object (
ase_stx_t* stx, const ase_char_t* str);
ase_word_t ase_stx_alloc_char_objectx (
ase_stx_t* stx, const ase_char_t* str, ase_word_t n);
ase_word_t ase_stx_allocn_char_object (ase_stx_t* stx, ...);
ase_word_t ase_stx_hash_object (ase_stx_t* stx, ase_word_t object);
ase_word_t ase_stx_instantiate (
ase_stx_t* stx, ase_word_t class_index, const void* data,
const void* variable_data, ase_word_t variable_nfields);
ase_word_t ase_stx_classof (ase_stx_t* stx, ase_word_t obj);
ase_word_t ase_stx_sizeof (ase_stx_t* stx, ase_word_t obj);
#ifdef __cplusplus
}
#endif
#endif

1608
ase/stx/parser.c Normal file

File diff suppressed because it is too large Load Diff

107
ase/stx/parser.h Normal file
View File

@ -0,0 +1,107 @@
/*
* $Id: parser.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_PARSER_H_
#define _ASE_STX_PARSER_H_
#include <ase/stx/stx.h>
#include <ase/stx/name.h>
#include <ase/stx/token.h>
#include <ase/bas/arr.h>
enum
{
ASE_STX_PARSER_ERROR_NONE,
/* system errors */
ASE_STX_PARSER_ERROR_INPUT_FUNC,
ASE_STX_PARSER_ERROR_INPUT,
ASE_STX_PARSER_ERROR_MEMORY,
/* lexical errors */
ASE_STX_PARSER_ERROR_CHAR,
ASE_STX_PARSER_ERROR_CHARLIT,
ASE_STX_PARSER_ERROR_STRLIT,
ASE_STX_PARSER_ERROR_LITERAL,
/* syntatic error */
ASE_STX_PARSER_ERROR_MESSAGE_SELECTOR,
ASE_STX_PARSER_ERROR_ARGUMENT_NAME,
ASE_STX_PARSER_ERROR_TOO_MANY_ARGUMENTS,
ASE_STX_PARSER_ERROR_PRIMITIVE_KEYWORD,
ASE_STX_PARSER_ERROR_PRIMITIVE_NUMBER,
ASE_STX_PARSER_ERROR_PRIMITIVE_NUMBER_RANGE,
ASE_STX_PARSER_ERROR_PRIMITIVE_NOT_CLOSED,
ASE_STX_PARSER_ERROR_TEMPORARIES_NOT_CLOSED,
ASE_STX_PARSER_ERROR_TOO_MANY_TEMPORARIES,
ASE_STX_PARSER_ERROR_PSEUDO_VARIABLE,
ASE_STX_PARSER_ERROR_PRIMARY,
ASE_STX_PARSER_ERROR_NO_PERIOD,
ASE_STX_PARSER_ERROR_NO_RPAREN,
ASE_STX_PARSER_ERROR_BLOCK_ARGUMENT_NAME,
ASE_STX_PARSER_ERROR_BLOCK_ARGUMENT_LIST,
ASE_STX_PARSER_ERROR_BLOCK_NOT_CLOSED,
ASE_STX_PARSER_ERROR_UNDECLARED_NAME,
ASE_STX_PARSER_ERROR_TOO_MANY_LITERALS
};
enum
{
/* input_func cmd */
ASE_STX_PARSER_INPUT_OPEN,
ASE_STX_PARSER_INPUT_CLOSE,
ASE_STX_PARSER_INPUT_CONSUME,
ASE_STX_PARSER_INPUT_REWIND
};
typedef struct ase_stx_parser_t ase_stx_parser_t;
struct ase_stx_parser_t
{
ase_stx_t* stx;
int error_code;
ase_word_t method_class;
ase_stx_name_t method_name;
ase_char_t* temporaries[256]; /* TODO: different size? or dynamic? */
ase_word_t argument_count;
ase_word_t temporary_count;
ase_word_t literals[256]; /* TODO: make it a dynamic array */
ase_word_t literal_count;
ase_arr_t bytecode;
ase_stx_token_t token;
ase_cint_t curc;
ase_cint_t ungotc[5];
ase_size_t ungotc_count;
void* input_owner;
int (*input_func) (int cmd, void* owner, void* arg);
ase_bool_t __dynamic;
};
#ifdef __cplusplus
extern "C" {
#endif
ase_stx_parser_t* ase_stx_parser_open (ase_stx_parser_t* parser, ase_stx_t* stx);
void ase_stx_parser_close (ase_stx_parser_t* parser);
const ase_char_t* ase_stx_parser_error_string (ase_stx_parser_t* parser);
int ase_stx_parser_parse_method (
ase_stx_parser_t* parser, ase_word_t method_class, void* input);
#ifdef __cplusplus
}
#endif
#endif

196
ase/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
ase/stx/stx.c Normal file
View File

@ -0,0 +1,70 @@
/*
* $Id: stx.c,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#include <ase/stx/stx.h>
#include <ase/stx/memory.h>
#include <ase/stx/misc.h>
ase_stx_t* ase_stx_open (ase_stx_t* stx, ase_word_t capacity)
{
ase_word_t i;
if (stx == ASE_NULL) {
stx = (ase_stx_t*)ase_malloc (ase_sizeof(stx));
if (stx == ASE_NULL) return ASE_NULL;
stx->__dynamic = ase_true;
}
else stx->__dynamic = ase_false;
if (ase_stx_memory_open (&stx->memory, capacity) == ASE_NULL) {
if (stx->__dynamic) ase_free (stx);
return ASE_NULL;
}
stx->symtab.size = 0;
stx->symtab.capacity = 128; /* TODO: symbol table size */
stx->symtab.datum = (ase_word_t*)ase_malloc (
ase_sizeof(ase_word_t) * stx->symtab.capacity);
if (stx->symtab.datum == ASE_NULL) {
ase_stx_memory_close (&stx->memory);
if (stx->__dynamic) ase_free (stx);
return ASE_NULL;
}
stx->nil = ASE_STX_NIL;
stx->true = ASE_STX_TRUE;
stx->false = ASE_STX_FALSE;
stx->smalltalk = ASE_STX_NIL;
stx->class_symbol = ASE_STX_NIL;
stx->class_metaclass = ASE_STX_NIL;
stx->class_association = ASE_STX_NIL;
stx->class_object = ASE_STX_NIL;
stx->class_class = ASE_STX_NIL;
stx->class_array = ASE_STX_NIL;
stx->class_bytearray = ASE_STX_NIL;
stx->class_string = ASE_STX_NIL;
stx->class_character = ASE_STX_NIL;
stx->class_context = ASE_STX_NIL;
stx->class_system_dictionary = ASE_STX_NIL;
stx->class_method = ASE_STX_NIL;
stx->class_smallinteger = ASE_STX_NIL;
for (i = 0; i < stx->symtab.capacity; i++) {
stx->symtab.datum[i] = stx->nil;
}
stx->__wantabort = ase_false;
return stx;
}
void ase_stx_close (ase_stx_t* stx)
{
ase_free (stx->symtab.datum);
ase_stx_memory_close (&stx->memory);
if (stx->__dynamic) ase_free (stx);
}

163
ase/stx/stx.h Normal file
View File

@ -0,0 +1,163 @@
/*
* $Id: stx.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_STX_H_
#define _ASE_STX_STX_H_
#include <ase/cmn/types.h>
#include <ase/cmn/macros.h>
typedef struct ase_stx_objhdr_t ase_stx_objhdr_t;
typedef struct ase_stx_object_t ase_stx_object_t;
typedef struct ase_stx_word_object_t ase_stx_word_object_t;
typedef struct ase_stx_byte_object_t ase_stx_byte_object_t;
typedef struct ase_stx_char_object_t ase_stx_char_object_t;
typedef struct ase_stx_memory_t ase_stx_memory_t;
typedef struct ase_stx_symtab_t ase_stx_symtab_t;
typedef struct ase_stx_t ase_stx_t;
/* common object structure */
struct ase_stx_objhdr_t
{
/* access - type: 2; size: rest;
* type - word indexed: 00 byte indexed: 01 char indexed: 10
*/
ase_word_t access;
ase_word_t class;
};
struct ase_stx_object_t
{
ase_stx_objhdr_t header;
};
struct ase_stx_word_object_t
{
ase_stx_objhdr_t header;
ase_word_t data[1];
};
struct ase_stx_byte_object_t
{
ase_stx_objhdr_t header;
ase_byte_t data[1];
};
struct ase_stx_char_object_t
{
ase_stx_objhdr_t header;
ase_char_t data[1];
};
struct ase_stx_memory_t
{
ase_word_t capacity;
ase_stx_object_t** slots;
ase_stx_object_t** free;
ase_bool_t __dynamic;
};
struct ase_stx_symtab_t
{
ase_word_t* datum;
ase_word_t size;
ase_word_t capacity;
};
struct ase_stx_t
{
ase_stx_memory_t memory;
ase_stx_symtab_t symtab;
ase_word_t nil;
ase_word_t true;
ase_word_t false;
ase_word_t smalltalk;
ase_word_t class_symbol;
ase_word_t class_metaclass;
ase_word_t class_association;
ase_word_t class_object;
ase_word_t class_class;
ase_word_t class_array;
ase_word_t class_bytearray;
ase_word_t class_string;
ase_word_t class_character;
ase_word_t class_context;
ase_word_t class_system_dictionary;
ase_word_t class_method;
ase_word_t class_smallinteger;
ase_bool_t __dynamic;
ase_bool_t __wantabort; /* TODO: make it a function pointer */
};
#define ASE_STX_IS_SMALLINT(x) (((x) & 0x01) == 0x01)
#define ASE_STX_TO_SMALLINT(x) (((x) << 1) | 0x01)
#define ASE_STX_FROM_SMALLINT(x) ((x) >> 1)
#define ASE_STX_IS_OINDEX(x) (((x) & 0x01) == 0x00)
#define ASE_STX_TO_OINDEX(x) (((x) << 1) | 0x00)
#define ASE_STX_FROM_OINDEX(x) ((x) >> 1)
#define ASE_STX_NIL ASE_STX_TO_OINDEX(0)
#define ASE_STX_TRUE ASE_STX_TO_OINDEX(1)
#define ASE_STX_FALSE ASE_STX_TO_OINDEX(2)
#define ASE_STX_OBJECT(stx,idx) (((stx)->memory).slots[ASE_STX_FROM_OINDEX(idx)])
#define ASE_STX_CLASS(stx,idx) (ASE_STX_OBJECT(stx,(idx))->header.class)
#define ASE_STX_ACCESS(stx,idx) (ASE_STX_OBJECT(stx,(idx))->header.access)
#define ASE_STX_DATA(stx,idx) ((void*)(ASE_STX_OBJECT(stx,idx) + 1))
#define ASE_STX_TYPE(stx,idx) (ASE_STX_ACCESS(stx,idx) & 0x03)
#define ASE_STX_SIZE(stx,idx) (ASE_STX_ACCESS(stx,idx) >> 0x02)
#define ASE_STX_WORD_INDEXED (0x00)
#define ASE_STX_BYTE_INDEXED (0x01)
#define ASE_STX_CHAR_INDEXED (0x02)
#define ASE_STX_IS_WORD_OBJECT(stx,idx) \
(ASE_STX_TYPE(stx,idx) == ASE_STX_WORD_INDEXED)
#define ASE_STX_IS_BYTE_OBJECT(stx,idx) \
(ASE_STX_TYPE(stx,idx) == ASE_STX_BYTE_INDEXED)
#define ASE_STX_IS_CHAR_OBJECT(stx,idx) \
(ASE_STX_TYPE(stx,idx) == ASE_STX_CHAR_INDEXED)
#define ASE_STX_WORD_OBJECT(stx,idx) \
((ase_stx_word_object_t*)ASE_STX_OBJECT(stx,idx))
#define ASE_STX_BYTE_OBJECT(stx,idx) \
((ase_stx_byte_object_t*)ASE_STX_OBJECT(stx,idx))
#define ASE_STX_CHAR_OBJECT(stx,idx) \
((ase_stx_char_object_t*)ASE_STX_OBJECT(stx,idx))
/*
#define ASE_STX_WORD_AT(stx,idx,n) \
(((ase_word_t*)(ASE_STX_OBJECT(stx,idx) + 1))[n])
#define ASE_STX_BYTE_AT(stx,idx,n) \
(((ase_byte_t*)(ASE_STX_OBJECT(stx,idx) + 1))[n])
#define ASE_STX_CHAR_AT(stx,idx,n) \
(((ase_char_t*)(ASE_STX_OBJECT(stx,idx) + 1))[n])
*/
#define ASE_STX_WORD_AT(stx,idx,n) \
(ASE_STX_WORD_OBJECT(stx,idx)->data[n])
#define ASE_STX_BYTE_AT(stx,idx,n) \
(ASE_STX_BYTE_OBJECT(stx,idx)->data[n])
#define ASE_STX_CHAR_AT(stx,idx,n) \
(ASE_STX_CHAR_OBJECT(stx,idx)->data[n])
#ifdef __cplusplus
extern "C" {
#endif
ase_stx_t* ase_stx_open (ase_stx_t* stx, ase_word_t capacity);
void ase_stx_close (ase_stx_t* stx);
#ifdef __cplusplus
}
#endif
#endif

90
ase/stx/stx.txt Normal file
View File

@ -0,0 +1,90 @@
stx(1) xpkit
NAME
stx - xpkit embeddable 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)
Chung, Hyung-Hwan (bacon@piowave.com) is the sole designer and implementer of stx.
BUG REPORTS
Report bugs to bacon@piowave.com if you find any bugs. but make sure that it is really a bug before you report it.
COPYRIGHT
Copyright(c) 2005 bacon@piowave.com
SEE ALSO
xpkit(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
ase/stx/symbol.c Normal file
View File

@ -0,0 +1,102 @@
/*
* $Id: symbol.c,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#include <ase/stx/symbol.h>
#include <ase/stx/object.h>
#include <ase/stx/misc.h>
static void __grow_symtab (ase_stx_t* stx)
{
ase_word_t capa, ncapa, i, j;
ase_word_t* nspace;
capa = stx->symtab.capacity;
ncapa = capa << 1;
nspace = (ase_word_t*)ase_malloc(ase_sizeof(ase_word_t) * ncapa);
if (nspace == ASE_NULL)
{
/* TODO: handle memory error */
}
for (i = 0; i < capa; i++)
{
ase_word_t x = stx->symtab.datum[i];
if (x == stx->nil) continue;
j = ase_stx_strxhash (
ASE_STX_DATA(stx,x), ASE_STX_SIZE(stx,x)) % ncapa;
while (1)
{
if (nspace[j] == stx->nil)
{
nspace[j] = x;
break;
}
j = (j % ncapa) + 1;
}
}
stx->symtab.capacity = ncapa;
ase_free (stx->symtab.datum);
stx->symtab.datum = nspace;
}
ase_word_t ase_stx_new_symbol (ase_stx_t* stx, const ase_char_t* name)
{
return ase_stx_new_symbolx (stx, name, ase_strlen(name));
}
ase_word_t ase_stx_new_symbolx (
ase_stx_t* stx, const ase_char_t* name, ase_word_t len)
{
ase_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 = ase_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 = ase_stx_alloc_char_objectx (stx, name, len);
ASE_STX_CLASS(stx,x) = stx->class_symbol;
stx->symtab.datum[index] = x;
stx->symtab.size++;
break;
}
if (ase_strxncmp(name, len,
ASE_STX_DATA(stx,x), ASE_STX_SIZE(stx,x)) == 0) break;
index = (index % stx->symtab.capacity) + 1;
}
return x;
}
void ase_stx_traverse_symbol_table (
ase_stx_t* stx, void (*func) (ase_stx_t*,ase_word_t,void*), void* data)
{
ase_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
ase/stx/symbol.h Normal file
View File

@ -0,0 +1,40 @@
/*
* $Id: symbol.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_SYMBOL_H_
#define _ASE_STX_SYMBOL_H_
#include <ase/stx/stx.h>
#define ASE_STX_SYMLINK_SIZE 2
#define ASE_STX_SYMLINK_LINK 0
#define ASE_STX_SYMLINK_SYMBOL 1
struct ase_stx_symlink_t
{
ase_stx_objhdr_t header;
ase_word_t link;
ase_word_t symbol;
};
typedef struct ase_stx_symlink_t ase_stx_symlink_t;
#ifdef __cplusplus
extern "C" {
#endif
ase_word_t ase_stx_new_symbol_link (ase_stx_t* stx, ase_word_t sym);
ase_word_t ase_stx_new_symbol (
ase_stx_t* stx, const ase_char_t* name);
ase_word_t ase_stx_new_symbolx (
ase_stx_t* stx, const ase_char_t* name, ase_word_t len);
void ase_stx_traverse_symbol_table (
ase_stx_t* stx, void (*func) (ase_stx_t*,ase_word_t,void*), void* data);
#ifdef __cplusplus
}
#endif
#endif

77
ase/stx/token.c Normal file
View File

@ -0,0 +1,77 @@
/*
* $Id: token.c,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#include <ase/stx/token.h>
#include <ase/stx/misc.h>
ase_stx_token_t* ase_stx_token_open (
ase_stx_token_t* token, ase_word_t capacity)
{
if (token == ASE_NULL) {
token = (ase_stx_token_t*)
ase_malloc (ase_sizeof(ase_stx_token_t));
if (token == ASE_NULL) return ASE_NULL;
token->__dynamic = ase_true;
}
else token->__dynamic = ase_false;
if (ase_stx_name_open(&token->name, capacity) == ASE_NULL) {
if (token->__dynamic) ase_free (token);
return ASE_NULL;
}
/*
token->ivalue = 0;
token->fvalue = .0;
*/
token->type = ASE_STX_TOKEN_END;
return token;
}
void ase_stx_token_close (ase_stx_token_t* token)
{
ase_stx_name_close (&token->name);
if (token->__dynamic) ase_free (token);
}
int ase_stx_token_addc (ase_stx_token_t* token, ase_cint_t c)
{
return ase_stx_name_addc (&token->name, c);
}
int ase_stx_token_adds (ase_stx_token_t* token, const ase_char_t* s)
{
return ase_stx_name_adds (&token->name, s);
}
void ase_stx_token_clear (ase_stx_token_t* token)
{
/*
token->ivalue = 0;
token->fvalue = .0;
*/
token->type = ASE_STX_TOKEN_END;
ase_stx_name_clear (&token->name);
}
ase_char_t* ase_stx_token_yield (ase_stx_token_t* token, ase_word_t capacity)
{
ase_char_t* p;
p = ase_stx_name_yield (&token->name, capacity);
if (p == ASE_NULL) return ASE_NULL;
/*
token->ivalue = 0;
token->fvalue = .0;
*/
token->type = ASE_STX_TOKEN_END;
return p;
}
int ase_stx_token_compare_name (ase_stx_token_t* token, const ase_char_t* str)
{
return ase_stx_name_compare (&token->name, str);
}

66
ase/stx/token.h Normal file
View File

@ -0,0 +1,66 @@
/*
* $Id: token.h,v 1.3 2007/04/30 08:32:41 bacon Exp $
*/
#ifndef _ASE_STX_TOKEN_H_
#define _ASE_STX_TOKEN_H_
#include <ase/stx/stx.h>
#include <ase/stx/name.h>
enum
{
ASE_STX_TOKEN_END,
ASE_STX_TOKEN_CHARLIT,
ASE_STX_TOKEN_STRLIT,
ASE_STX_TOKEN_SYMLIT,
ASE_STX_TOKEN_NUMLIT,
ASE_STX_TOKEN_IDENT,
ASE_STX_TOKEN_BINARY,
ASE_STX_TOKEN_KEYWORD,
ASE_STX_TOKEN_PRIMITIVE,
ASE_STX_TOKEN_ASSIGN,
ASE_STX_TOKEN_COLON,
ASE_STX_TOKEN_RETURN,
ASE_STX_TOKEN_LBRACKET,
ASE_STX_TOKEN_RBRACKET,
ASE_STX_TOKEN_LPAREN,
ASE_STX_TOKEN_RPAREN,
ASE_STX_TOKEN_APAREN,
ASE_STX_TOKEN_PERIOD,
ASE_STX_TOKEN_SEMICOLON
};
struct ase_stx_token_t
{
int type;
/*
ase_stx_int_t ivalue;
ase_stx_real_t fvalue;
*/
ase_stx_name_t name;
ase_bool_t __dynamic;
};
typedef struct ase_stx_token_t ase_stx_token_t;
#ifdef __cplusplus
extern "C" {
#endif
ase_stx_token_t* ase_stx_token_open (
ase_stx_token_t* token, ase_word_t capacity);
void ase_stx_token_close (ase_stx_token_t* token);
int ase_stx_token_addc (ase_stx_token_t* token, ase_cint_t c);
int ase_stx_token_adds (ase_stx_token_t* token, const ase_char_t* s);
void ase_stx_token_clear (ase_stx_token_t* token);
ase_char_t* ase_stx_token_yield (ase_stx_token_t* token, ase_word_t capacity);
int ase_stx_token_compare_name (ase_stx_token_t* token, const ase_char_t* str);
#ifdef __cplusplus
}
#endif
#endif