qse/qse/lib/stx/cls.c

213 lines
5.1 KiB
C

/*
* $Id$
*/
#include "stx.h"
#if 0
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;
}
int qse_stx_get_instance_variable_index (
qse_stx_t* stx, qse_word_t class_index,
const qse_char_t* name, qse_word_t* index)
{
qse_word_t index_super = 0;
qse_stx_class_t* class_obj;
qse_stx_char_object_t* string;
class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class_index);
qse_assert (class_obj != QSE_NULL);
if (class_obj->superclass != stx->nil) {
if (qse_stx_get_instance_variable_index (
stx, class_obj->superclass, name, &index_super) == 0) {
*index = index_super;
return 0;
}
}
if (class_obj->header.class == stx->class_metaclass) {
/* metaclass */
/* TODO: can a metaclas have instance variables? */
*index = index_super;
}
else {
if (class_obj->variables == stx->nil) *index = 0;
else {
string = QSE_STX_CHAR_OBJECT(stx, class_obj->variables);
if (qse_stx_strword(string->data, name, index) != QSE_NULL) {
*index += index_super;
return 0;
}
}
*index += index_super;
}
return -1;
}
qse_word_t qse_stx_lookup_class_variable (
qse_stx_t* stx, qse_word_t class_index, const qse_char_t* name)
{
qse_stx_class_t* class_obj;
class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class_index);
qse_assert (class_obj != QSE_NULL);
if (class_obj->superclass != stx->nil) {
qse_word_t tmp;
tmp = qse_stx_lookup_class_variable (
stx, class_obj->superclass, name);
if (tmp != stx->nil) return tmp;
}
/* TODO: can a metaclas have class variables? */
if (class_obj->header.class != stx->class_metaclass &&
class_obj->class_variables != stx->nil) {
if (qse_stx_dict_lookup(stx,
class_obj->class_variables,name) != stx->nil) return class_index;
}
return stx->nil;
}
qse_word_t qse_stx_lookup_method (qse_stx_t* stx,
qse_word_t class_index, const qse_char_t* name, qse_bool_t from_super)
{
qse_stx_class_t* class_obj;
class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class_index);
qse_assert (class_obj != QSE_NULL);
#if 0
if (class_obj->header.class != stx->class_metaclass &&
class_obj->methods != stx->nil) {
qse_word_t assoc;
assoc = qse_stx_dict_lookup(stx, class_obj->methods, name);
if (assoc != stx->nil) {
qse_assert (QSE_STX_CLASS(stx,assoc) == stx->class_association);
return QSE_STX_WORD_AT(stx, assoc, QSE_STX_ASSOCIATION_VALUE);
}
}
if (class_obj->superclass != stx->nil) {
qse_word_t tmp;
tmp = qse_stx_lookup_method (
stx, class_obj->superclass, name);
if (tmp != stx->nil) return tmp;
}
#endif
while (class_index != stx->nil) {
class_obj = (qse_stx_class_t*)QSE_STX_OBJPTR(stx, class_index);
qse_assert (class_obj != QSE_NULL);
qse_assert (
class_obj->header.class == stx->class_metaclass ||
QSE_STX_CLASS(stx,class_obj->header.class) == stx->class_metaclass);
if (from_super) {
from_super = qse_false;
}
else if (class_obj->methods != stx->nil) {
qse_word_t assoc;
assoc = qse_stx_dict_lookup(stx, class_obj->methods, name);
if (assoc != stx->nil) {
qse_assert (QSE_STX_CLASS(stx,assoc) == stx->class_association);
return QSE_STX_WORD_AT(stx, assoc, QSE_STX_ASSOCIATION_VALUE);
}
}
class_index = class_obj->superclass;
}
return stx->nil;
}
#endif
qse_word_t qse_stx_instantiate (
qse_stx_t* stx, qse_word_t classref, const void* data,
const void* variable_data, qse_word_t variable_nflds)
{
qse_stx_class_t* classptr;
qse_word_t spec, nflds, inst;
int variable;
QSE_ASSERT (REFISIDX(stx,classref));
/* don't instantiate a metaclass whose instance must be
created in a different way */
QSE_ASSERT (OBJCLASS(stx,classref) != stx->ref.class_metaclass);
classptr = (qse_stx_class_t*)PTRBYREF(stx,classref);
QSE_ASSERT (REFISINT(stx,classptr->spec));
spec = REFTOINT(stx,classptr->spec);
nflds = (spec >> SPEC_VARIABLE_BITS);
variable = spec & SPEC_VARIABLE_MASK;
switch (variable)
{
case SPEC_VARIABLE_BYTE:
/* variable-size byte class */
QSE_ASSERT (nflds == 0 && data == QSE_NULL);
inst = qse_stx_allocbyteobj (
stx, variable_data, variable_nflds);
break;
case SPEC_VARIABLE_CHAR:
/* variable-size char class */
QSE_ASSERT (nflds == 0 && data == QSE_NULL);
inst = qse_stx_alloccharobj (
stx, variable_data, variable_nflds);
break;
case SPEC_VARIABLE_WORD:
/* variable-size class */
inst = qse_stx_allocwordobj (
stx, data, nflds, variable_data, variable_nflds);
break;
case SPEC_FIXED_WORD:
/* fixed size */
QSE_ASSERT (variable_nflds == 0 && variable_data == QSE_NULL);
inst = qse_stx_allocwordobj (
stx, data, nflds, QSE_NULL, 0);
break;
default:
/* this should never happen */
QSE_ASSERTX (0, "this should never happen");
qse_stx_seterrnum (stx, QSE_STX_EINTERN, QSE_NULL);
return stx->ref.nil;
}
QSE_ASSERT (inst != stx->ref.nil);
OBJCLASS(stx,inst) = classref;
return inst;
}