added many lines of code for initial loading
This commit is contained in:
parent
c74266293d
commit
0b97fee2c4
166
stix/lib/dic.c
Normal file
166
stix/lib/dic.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2014-2015 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stix-prv.h"
|
||||
|
||||
static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t old_bucket)
|
||||
{
|
||||
stix_oop_oop_t new_bucket;
|
||||
stix_oow_t oldsz, newsz, index;
|
||||
stix_oop_association_t ass;
|
||||
stix_oop_char_t key;
|
||||
|
||||
/* TODO: derive a better growth size */
|
||||
new_bucket = (stix_oop_oop_t)stix_instantiate (stix, stix->_array, STIX_NULL, STIX_OBJ_GET_SIZE(old_bucket) * 2);
|
||||
if (!new_bucket) return STIX_NULL;
|
||||
|
||||
oldsz = STIX_OBJ_GET_SIZE(old_bucket);
|
||||
newsz = STIX_OBJ_GET_SIZE(new_bucket);
|
||||
|
||||
while (oldsz > 0)
|
||||
{
|
||||
ass = (stix_oop_association_t)old_bucket->slot[--oldsz];
|
||||
if ((stix_oop_t)ass != stix->_nil)
|
||||
{
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,ass) == stix->_association);
|
||||
|
||||
key = (stix_oop_char_t)ass->key;
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,key) == (stix_oop_t)stix->_symbol);
|
||||
|
||||
index = stix_hashchars (key->slot, STIX_OBJ_GET_SIZE(key)) % newsz;
|
||||
while (new_bucket->slot[index] != stix->_nil)
|
||||
index = (index + 1) % newsz;
|
||||
new_bucket->slot[index] = (stix_oop_t)ass;
|
||||
}
|
||||
}
|
||||
|
||||
return new_bucket;
|
||||
}
|
||||
|
||||
stix_oop_t find_or_insert (stix_t* stix, stix_oop_char_t key, stix_oop_t value)
|
||||
{
|
||||
stix_oow_t index, tally;
|
||||
stix_oop_association_t ass;
|
||||
stix_oow_t tmp_count = 0;
|
||||
|
||||
/* the system dictionary is not a generic dictionary.
|
||||
* it accepts only a symbol as a key. */
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,key) == stix->_symbol);
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,stix->sysdic->tally) == stix->_small_integer);
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,stix->sysdic->bucket) == stix->_array);
|
||||
|
||||
index = stix_hashchars(key->slot, STIX_OBJ_GET_SIZE(key)) % STIX_OBJ_GET_SIZE(stix->sysdic->bucket);
|
||||
|
||||
while (stix->sysdic->bucket->slot[index] != stix->_nil)
|
||||
{
|
||||
ass = (stix_oop_association_t)stix->sysdic->bucket->slot[index];
|
||||
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,ass) == stix->_association);
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,ass->key) == stix->_symbol);
|
||||
|
||||
if (STIX_OBJ_GET_SIZE(key) == STIX_OBJ_GET_SIZE(ass->key))
|
||||
{
|
||||
stix_oow_t i;
|
||||
|
||||
for (i = 0; i < STIX_OBJ_GET_SIZE(key); i++)
|
||||
{
|
||||
if (key->slot[i] != ((stix_oop_char_t)ass->key)->slot[i]) goto not_equal;
|
||||
}
|
||||
return (stix_oop_t)ass;
|
||||
}
|
||||
|
||||
not_equal:
|
||||
index = (index + 1) % STIX_OBJ_GET_SIZE(stix->sysdic->bucket);
|
||||
}
|
||||
|
||||
if (value == STIX_NULL)
|
||||
{
|
||||
/*
|
||||
stix->errnum = STIX_ENOENT;
|
||||
return STIX_NULL;
|
||||
*/
|
||||
return stix->_nil;
|
||||
}
|
||||
|
||||
stix_pushtmp (stix, (stix_oop_t*)&key); tmp_count++;
|
||||
stix_pushtmp (stix, &value); tmp_count++;
|
||||
|
||||
tally = STIX_OOP_TO_SMINT(stix->sysdic->tally);
|
||||
if (tally + 1 >= STIX_OBJ_GET_SIZE(stix->sysdic->bucket))
|
||||
{
|
||||
stix_oop_oop_t bucket;
|
||||
|
||||
/* TODO: make the growth policy configurable instead of growing
|
||||
it just before it gets full. The polcy can be grow it
|
||||
if it's 70% full */
|
||||
|
||||
/* Enlarge the symbol table before it gets full to
|
||||
* make sure that it has at least one free slot left
|
||||
* after having added a new symbol. this is to help
|
||||
* traversal end at a _nil slot if no entry is found. */
|
||||
bucket = expand_bucket (stix, stix->sysdic->bucket);
|
||||
if (!bucket) goto oops;
|
||||
|
||||
stix->sysdic->bucket = bucket;
|
||||
|
||||
/* recalculate the index for the expanded bucket */
|
||||
index = stix_hashchars(key->slot, STIX_OBJ_GET_SIZE(key)) % STIX_OBJ_GET_SIZE(stix->sysdic->bucket);
|
||||
|
||||
while (stix->sysdic->bucket->slot[index] != stix->_nil)
|
||||
index = (index + 1) % STIX_OBJ_GET_SIZE(stix->sysdic->bucket);
|
||||
}
|
||||
|
||||
/* create a new assocation of a key and a value since
|
||||
* the key isn't found in the root dictionary */
|
||||
ass = (stix_oop_association_t)stix_instantiate (stix, stix->_association, STIX_NULL, 0);
|
||||
if (!ass)
|
||||
{
|
||||
ass->key = (stix_oop_t)key;
|
||||
ass->value = value;
|
||||
}
|
||||
|
||||
stix->sysdic->tally = STIX_OOP_FROM_SMINT(tally + 1);
|
||||
stix->sysdic->bucket->slot[index] = (stix_oop_t)ass;
|
||||
|
||||
stix_poptmps (stix, tmp_count);
|
||||
return (stix_oop_t)ass;
|
||||
|
||||
oops:
|
||||
stix_poptmps (stix, tmp_count);
|
||||
return STIX_NULL;
|
||||
}
|
||||
|
||||
stix_oop_t stix_putatsysdic (stix_t* stix, stix_oop_t key, stix_oop_t value)
|
||||
{
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,key) == stix->_symbol);
|
||||
return find_or_insert (stix, (stix_oop_char_t)key, value);
|
||||
}
|
||||
|
||||
stix_oop_t stix_getatsysdic (stix_t* stix, stix_oop_t key)
|
||||
{
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,key) == stix->_symbol);
|
||||
return find_or_insert (stix, (stix_oop_char_t)key, STIX_NULL);
|
||||
}
|
126
stix/lib/gc.c
126
stix/lib/gc.c
@ -28,63 +28,73 @@
|
||||
|
||||
static void cleanup_symbols_for_gc (stix_t* stix, stix_oop_t _nil)
|
||||
{
|
||||
#if 0
|
||||
stix_oop_oop_t buc;
|
||||
stix_oop_char_t sym;
|
||||
stix_oop_char_t symbol;
|
||||
stix_oow_t tally, index, i, x, y, z;
|
||||
stix_oow_t bucket_size;
|
||||
|
||||
tally = STIX_OOP_TO_SMINT (stix->symtab->slot[STIX_SYMTAB_TALLY]);
|
||||
#if defined(STIX_SUPPORT_GC_DURING_IGNITION)
|
||||
if (!stix->symtab) return; /* symbol table has not been created */
|
||||
#endif
|
||||
|
||||
bucket_size = STIX_OBJ_GET_SIZE(stix->symtab->bucket);
|
||||
|
||||
tally = STIX_OOP_TO_SMINT(stix->symtab->tally);
|
||||
if (tally <= 0) return;
|
||||
|
||||
buc = (stix_oop_oop_t) stix->symtab->slot[STIX_SYMTAB_BUCKET];
|
||||
for (index = 0; index < buc->size; )
|
||||
for (index = 0; index < bucket_size; )
|
||||
{
|
||||
if (buc->slot[index]->flags & STIX_OBJ_FLAG_MOVED)
|
||||
if (STIX_OBJ_GET_FLAGS_MOVED(stix->symtab->bucket->slot[index]))
|
||||
{
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
STIX_ASSERT (buc->slot[index] != _nil);
|
||||
STIX_ASSERT (stix->symtab->bucket->slot[index] != _nil);
|
||||
|
||||
/*
|
||||
{
|
||||
sym = (stix_oop_char_t)buc->slot[index];
|
||||
wprintf (L">> DISPOSING %d [%S] from the symbol table\n", (int)index, sym->slot);
|
||||
}
|
||||
for (i = 0, x = index, y = index; i < buc->size; i++)
|
||||
*/
|
||||
|
||||
for (i = 0, x = index, y = index; i < bucket_size; i++)
|
||||
{
|
||||
y = (y + 1) % buc->size;
|
||||
y = (y + 1) % bucket_size;
|
||||
|
||||
/* done if the slot at the current hash index is _nil */
|
||||
if (buc->slot[y] == _nil) break;
|
||||
if (stix->symtab->bucket->slot[y] == _nil) break;
|
||||
|
||||
/* get the natural hash index for the data in the slot
|
||||
* at the current hash index */
|
||||
sym = (stix_oop_char_t)buc->slot[y];
|
||||
symbol = (stix_oop_char_t)stix->symtab->bucket->slot[y];
|
||||
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,sym) == (stix_oop_t)stix->cc.symbol);
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,symbol) == stix->_symbol);
|
||||
|
||||
z = hash_chars (sym->slot, sym->size) % buc->size;
|
||||
z = stix_hashchars(symbol->slot, STIX_OBJ_GET_SIZE(symbol)) % bucket_size;
|
||||
|
||||
/* move an element if necessary */
|
||||
if ((y > x && (z <= x || z > y)) ||
|
||||
(y < x && (z <= x && z > y)))
|
||||
{
|
||||
buc->slot[x] = buc->slot[y];
|
||||
stix->symtab->bucket->slot[x] = stix->symtab->bucket->slot[y];
|
||||
x = y;
|
||||
}
|
||||
}
|
||||
|
||||
buc->slot[x] = _nil;
|
||||
stix->symtab->bucket->slot[x] = _nil;
|
||||
tally--;
|
||||
}
|
||||
|
||||
stix->symtab->slot[STIX_SYMTAB_TALLY] = STIX_OOP_FROM_SMINT(tally);
|
||||
#endif
|
||||
stix->symtab->tally = STIX_OOP_FROM_SMINT(tally);
|
||||
}
|
||||
|
||||
static stix_oop_t move_one (stix_t* stix, stix_oop_t oop)
|
||||
{
|
||||
#if defined(STIX_SUPPORT_GC_DURING_IGNITION)
|
||||
if (!oop) return oop;
|
||||
#endif
|
||||
|
||||
STIX_ASSERT (STIX_OOP_IS_POINTER(oop));
|
||||
|
||||
if (STIX_OBJ_GET_FLAGS_MOVED(oop))
|
||||
@ -93,7 +103,7 @@ static stix_oop_t move_one (stix_t* stix, stix_oop_t oop)
|
||||
* the class field has been updated to the new object
|
||||
* in the 'else' block below. i can simply return it
|
||||
* without further migration. */
|
||||
return oop->_class;
|
||||
return STIX_OBJ_GET_CLASS(oop);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -125,8 +135,8 @@ static stix_oop_t move_one (stix_t* stix, stix_oop_t oop)
|
||||
/* let the class field of the old object point to the new
|
||||
* object allocated in the new heap. it is returned in
|
||||
* the 'if' block at the top of this function. */
|
||||
oop->_class = tmp;
|
||||
|
||||
STIX_OBJ_SET_CLASS (oop, tmp);
|
||||
|
||||
/* return the new object */
|
||||
return tmp;
|
||||
}
|
||||
@ -141,11 +151,10 @@ static stix_uint8_t* scan_new_heap (stix_t* stix, stix_uint8_t* ptr)
|
||||
stix_oop_t oop;
|
||||
|
||||
oop = (stix_oop_t)ptr;
|
||||
nbytes = (oop->_size + STIX_OBJ_GET_FLAGS_EXTRA(oop)) * STIX_OBJ_GET_FLAGS_UNIT(oop);
|
||||
nbytes = (STIX_OBJ_GET_SIZE(oop) + STIX_OBJ_GET_FLAGS_EXTRA(oop)) * STIX_OBJ_GET_FLAGS_UNIT(oop);
|
||||
nbytes_aligned = STIX_ALIGN (nbytes, STIX_SIZEOF(stix_oop_t));
|
||||
|
||||
oop->_class = move_one (stix, oop->_class);
|
||||
|
||||
STIX_OBJ_SET_CLASS (oop, move_one(stix, STIX_OBJ_GET_CLASS(oop)));
|
||||
if (STIX_OBJ_GET_FLAGS_TYPE(oop) == STIX_OBJ_TYPE_OOP)
|
||||
{
|
||||
stix_obj_oop_t* xtmp;
|
||||
@ -157,7 +166,7 @@ static stix_uint8_t* scan_new_heap (stix_t* stix, stix_uint8_t* ptr)
|
||||
xtmp->slot[i] = move_one (stix, xtmp->slot[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*wprintf (L"ptr in gc => %p size => %d, aligned size => %d\n", ptr, (int)nbytes, (int)nbytes_aligned);*/
|
||||
ptr = ptr + STIX_SIZEOF(stix_obj_t) + nbytes_aligned;
|
||||
}
|
||||
@ -174,30 +183,40 @@ void stix_gc (stix_t* stix)
|
||||
* move objects pointed to by the fields to the new heap.
|
||||
* finally perform some tricky symbol table clean-up.
|
||||
*/
|
||||
|
||||
stix_uint8_t* ptr;
|
||||
stix_heap_t* tmp;
|
||||
stix_oop_t old__nil;
|
||||
stix_oop_t old_nil;
|
||||
stix_oow_t i;
|
||||
|
||||
/* TODO: allocate common objects like _nil and the root dictionary
|
||||
* in the permanant heap. minimize moving around */
|
||||
|
||||
old__nil = stix->_nil;
|
||||
old_nil = stix->_nil;
|
||||
|
||||
/* move _nil and the root object table */
|
||||
stix->_nil = move_one (stix, stix->_nil);
|
||||
stix->root = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->root);
|
||||
stix->_true = move_one (stix, stix->_true);
|
||||
stix->_false = move_one (stix, stix->_false);
|
||||
stix->_nil = move_one (stix, stix->_nil);
|
||||
stix->_true = move_one (stix, stix->_true);
|
||||
stix->_false = move_one (stix, stix->_false);
|
||||
|
||||
stix->cc.array = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.array);
|
||||
stix->cc.association = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.association);
|
||||
/*stix->cc.metaclass = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.metaclass);*/
|
||||
stix->cc.string = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.string);
|
||||
stix->cc.symbol = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.symbol);
|
||||
stix->cc.sysdic = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.sysdic);
|
||||
stix->cc.numeric[0] = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.numeric[0]);
|
||||
stix->cc.numeric[1] = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->cc.numeric[1]);
|
||||
/*printf ("BEFORE GC = %p %p %p %p %p %p %p %p %p %p\n", stix->_array, stix->_class, stix->_nil_object, stix->_object, stix->_symbol, stix->_symbol_set, stix->_system_dictionary, stix->_association, stix->_character, stix->_small_integer);*/
|
||||
stix->_stix = move_one (stix, stix->_stix);
|
||||
stix->_class = move_one (stix, stix->_class);
|
||||
stix->_nil_object = move_one (stix, stix->_nil_object);
|
||||
stix->_object = move_one (stix, stix->_object);
|
||||
stix->_array = move_one (stix, stix->_array);
|
||||
stix->_symbol = move_one (stix, stix->_symbol);
|
||||
stix->_symbol_set = move_one (stix, stix->_symbol_set);
|
||||
stix->_system_dictionary = move_one (stix, stix->_system_dictionary);
|
||||
stix->_association = move_one (stix, stix->_association);
|
||||
stix->_character = move_one (stix, stix->_character);
|
||||
stix->_small_integer = move_one (stix, stix->_small_integer);
|
||||
|
||||
/*printf ("AFTER GC = %p %p %p %p %p %p %p %p %p %p\n", stix->_array, stix->_class, stix->_nil_object, stix->_object, stix->_symbol, stix->_symbol_set, stix->_system_dictionary, stix->_association, stix->_character, stix->_small_integer);*/
|
||||
stix->sysdic = (stix_oop_set_t) move_one (stix, (stix_oop_t)stix->sysdic);
|
||||
|
||||
for (i = 0; i < stix->tmp_count; i++)
|
||||
{
|
||||
*stix->tmp_stack[i] = move_one (stix, *stix->tmp_stack[i]);
|
||||
}
|
||||
|
||||
/* scan the new heap to move referenced objects */
|
||||
ptr = (stix_uint8_t*) STIX_ALIGN ((stix_uintptr_t)stix->newheap->base, STIX_SIZEOF(stix_oop_t));
|
||||
@ -207,10 +226,10 @@ void stix_gc (stix_t* stix)
|
||||
* if the symbol has not moved to the new heap, the symbol
|
||||
* is not referenced by any other objects than the symbol
|
||||
* table itself */
|
||||
cleanup_symbols_for_gc (stix, old__nil);
|
||||
cleanup_symbols_for_gc (stix, old_nil);
|
||||
|
||||
/* move the symbol table itself */
|
||||
stix->symtab = (stix_oop_oop_t) move_one (stix, (stix_oop_t)stix->symtab);
|
||||
stix->symtab = (stix_oop_set_t)move_one (stix, (stix_oop_t)stix->symtab);
|
||||
|
||||
/* scan the new heap again from the end position of
|
||||
* the previous scan to move referenced objects by
|
||||
@ -242,3 +261,24 @@ printf ("===========================\n");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void stix_pushtmp (stix_t* stix, stix_oop_t* oop_ptr)
|
||||
{
|
||||
/* if you have too many temporaries pushed, something must be wrong.
|
||||
* change your code not to exceede the stack limit */
|
||||
STIX_ASSERT (stix->tmp_count < STIX_COUNTOF(stix->tmp_stack));
|
||||
stix->tmp_stack[stix->tmp_count++] = oop_ptr;
|
||||
}
|
||||
|
||||
void stix_poptmp (stix_t* stix)
|
||||
{
|
||||
STIX_ASSERT (stix->tmp_count > 0);
|
||||
stix->tmp_count--;
|
||||
}
|
||||
|
||||
void stix_poptmps (stix_t* stix, stix_oow_t count)
|
||||
{
|
||||
STIX_ASSERT (stix->tmp_count >= count);
|
||||
stix->tmp_count -= count;
|
||||
}
|
||||
|
@ -27,6 +27,204 @@
|
||||
#include "stix-prv.h"
|
||||
|
||||
|
||||
#if 0
|
||||
stix_oop_t stix_addclass (stix_t* stix, name, spec, ...)
|
||||
{
|
||||
/* convert name to the internal encoding... */
|
||||
|
||||
/* returned value must be also registered in the system dictionary.
|
||||
* so it doesn't get GCed. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
int stix_delclass (stix_t* stix, stix_oop_t _class)
|
||||
{
|
||||
stix_oop_class_t c = (stix_oop_class_t)_class;
|
||||
|
||||
if (c->name)
|
||||
{
|
||||
/* delete c->name from system dictionary. it'll get GCed if it's not referenced */
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
stix_oop_t stix_findclass (stix_t* stix, const char* name)
|
||||
{
|
||||
/* find a class object by name */
|
||||
return STIX_NULL;
|
||||
}
|
||||
|
||||
int stix_addmethod (stix_t* stix, stix_oop_t _class, const char* name, const bytecode)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Stix .....................
|
||||
* ^ ^ ^ : .......
|
||||
* | | | v v :
|
||||
* | | +------------------- Class .....
|
||||
* | | ^ ^
|
||||
* | +-------- NilObject ......: :
|
||||
* | ^........ nil :
|
||||
* Object ...........................:
|
||||
* ^
|
||||
* |
|
||||
*
|
||||
* The class hierarchy is roughly as follows:
|
||||
*
|
||||
* Stix
|
||||
* Class
|
||||
* NilObject
|
||||
* Object
|
||||
* Collection
|
||||
* IndexedCollection
|
||||
* FixedSizedCollection
|
||||
* Array
|
||||
* ByteArray
|
||||
* String
|
||||
* Symbol
|
||||
* Set
|
||||
* Dictionary
|
||||
* SystemDictionary
|
||||
* SymbolSet
|
||||
* Magnitude
|
||||
* Association
|
||||
* Character
|
||||
* Number
|
||||
* Integer
|
||||
* SmallInteger
|
||||
* LargeInteger
|
||||
*
|
||||
* Stix has no instance variables.
|
||||
* Stix has 1 class variable: Sysdic
|
||||
*
|
||||
*/
|
||||
|
||||
static stix_oop_t alloc_kernel_class (stix_t* stix, stix_oow_t indexed, stix_oow_t spec)
|
||||
{
|
||||
stix_oop_class_t c;
|
||||
|
||||
c = (stix_oop_class_t)stix_allocoopobj (stix, STIX_CLASS_NAMED_INSTVARS + indexed);
|
||||
if (!c) return STIX_NULL;
|
||||
|
||||
STIX_OBJ_SET_FLAGS_KERNEL (c, 1);
|
||||
STIX_OBJ_SET_CLASS (c, stix->_class);
|
||||
c->spec = STIX_OOP_FROM_SMINT(spec);
|
||||
|
||||
return (stix_oop_t)c;
|
||||
}
|
||||
|
||||
static int ignite_1 (stix_t* stix)
|
||||
{
|
||||
/*
|
||||
* Create fundamental class objects with some fields mis-initialized yet.
|
||||
* Such fields include 'superclass', 'subclasses', 'name', etc.
|
||||
*/
|
||||
STIX_ASSERT (stix->_nil != STIX_NULL);
|
||||
STIX_ASSERT (STIX_OBJ_GET_CLASS(stix->_nil) == STIX_NULL);
|
||||
|
||||
/* --------------------------------------------------------------
|
||||
* Class
|
||||
* The instance of Class can have indexed instance variables
|
||||
* which are actually class variables.
|
||||
* -------------------------------------------------------------- */
|
||||
stix->_class = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE (STIX_CLASS_NAMED_INSTVARS, 1, STIX_OBJ_TYPE_OOP));
|
||||
if (!stix->_class) return -1;
|
||||
|
||||
STIX_ASSERT (STIX_OBJ_GET_CLASS(stix->_class) == STIX_NULL);
|
||||
STIX_OBJ_SET_CLASS (stix->_class, stix->_class);
|
||||
|
||||
/* --------------------------------------------------------------
|
||||
* Stix - proto-object with 1 class variable.
|
||||
* NilObject - class for the nil object.
|
||||
* Object - top of all ordinary objects.
|
||||
* Symbol
|
||||
* Array
|
||||
* SymbolSet
|
||||
* Character
|
||||
* SmallIntger
|
||||
* -------------------------------------------------------------- */
|
||||
stix->_stix = alloc_kernel_class (stix, 1, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP));
|
||||
stix->_nil_object = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP));
|
||||
stix->_object = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP));
|
||||
stix->_array = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 1, STIX_OBJ_TYPE_OOP));
|
||||
stix->_symbol = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 1, STIX_OBJ_TYPE_CHAR));
|
||||
stix->_symbol_set = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_SET_NAMED_INSTVARS, 0, STIX_OBJ_TYPE_OOP));
|
||||
stix->_system_dictionary = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_SET_NAMED_INSTVARS, 0, STIX_OBJ_TYPE_OOP));
|
||||
stix->_association = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_ASSOCIATION_NAMED_INSTVARS, 0, STIX_OBJ_TYPE_OOP));
|
||||
|
||||
/* TOOD: what is a proper spec for Character and SmallInteger?
|
||||
* If the fixed part is 0, its instance must be an object of 0 payload fields.
|
||||
* Does this make sense? */
|
||||
stix->_character = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP));
|
||||
stix->_small_integer = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP));
|
||||
|
||||
if (!stix->_stix || !stix->_nil_object || !stix->_object ||
|
||||
!stix->_array || !stix->_symbol || !stix->_symbol_set ||
|
||||
!stix->_system_dictionary || !stix->_association ||
|
||||
!stix->_character || !stix->_small_integer) return -1;
|
||||
|
||||
STIX_OBJ_SET_CLASS (stix->_nil, stix->_nil_object);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ignite_2 (stix_t* stix)
|
||||
{
|
||||
stix_oop_oop_t arr;
|
||||
|
||||
/* Create the symbol table */
|
||||
stix->symtab = (stix_oop_set_t)stix_instantiate (stix, stix->_symbol_set, STIX_NULL, 0);
|
||||
if (!stix->symtab) return -1;
|
||||
|
||||
stix->symtab->tally = STIX_OOP_FROM_SMINT(0);
|
||||
arr = (stix_oop_oop_t)stix_instantiate (stix, stix->_array, STIX_NULL, stix->option.default_symtab_size);
|
||||
if (!arr) return -1;
|
||||
stix->symtab->bucket = arr;
|
||||
|
||||
/* Create the system dictionary */
|
||||
stix->sysdic = (stix_oop_set_t)stix_instantiate (stix, stix->_system_dictionary, STIX_NULL, 0);
|
||||
if (!stix->sysdic) return -1;
|
||||
|
||||
stix->sysdic->tally = STIX_OOP_FROM_SMINT(0);
|
||||
arr = (stix_oop_oop_t)stix_instantiate (stix, stix->_array, STIX_NULL, stix->option.default_sysdic_size);
|
||||
if (!arr) return -1;
|
||||
stix->sysdic->bucket = arr;
|
||||
|
||||
/* Export the system dictionary via the first class variable of the Stix class */
|
||||
((stix_oop_class_t)stix->_stix)->classvar[0] = (stix_oop_t)stix->sysdic;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/*
|
||||
stix_oop_class_t c;
|
||||
|
||||
c = (stix_oop_class_t)stix->_stix;
|
||||
c->classvar[0] = stix->_nil;
|
||||
*/
|
||||
/* Set subclasses */
|
||||
|
||||
/*
|
||||
Set Names.
|
||||
stix->_stix_object->name = new_symbol ("ProtoObject");
|
||||
stix->_nil_object->name = new_symbol ("NilObject");
|
||||
stix->_class->name = new_symbol ("Class");
|
||||
*/
|
||||
|
||||
/*
|
||||
_class->instvars = make_string or make_array('spec instmthds classmthds superclass name instvars');
|
||||
*/
|
||||
|
||||
/*register 'Stix', 'NilObject' and 'Class' into the system dictionary.*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int stix_ignite (stix_t* stix)
|
||||
{
|
||||
STIX_ASSERT (stix->_nil == STIX_NULL);
|
||||
@ -35,11 +233,11 @@ int stix_ignite (stix_t* stix)
|
||||
if (!stix->_nil) return -1;
|
||||
|
||||
stix->_nil->_flags = STIX_OBJ_MAKE_FLAGS (STIX_OBJ_TYPE_OOP, STIX_SIZEOF(stix_oop_t), 0, 1, 0);
|
||||
stix->_nil->_size= 0;
|
||||
stix->_nil->_class = stix->_nil;
|
||||
stix->_nil->_size = 0;
|
||||
|
||||
if (ignite_1(stix) <= -1 || ignite_2(stix) <= -1) return -1;
|
||||
|
||||
printf ("%lu\n", (unsigned long int)stix->_nil->_flags);
|
||||
/*stix_addclass (stix, "True", spec, "Boolean");*/
|
||||
/*stix->_true = stix_instantiate (stix, stix->_true_class, STIX_NULL, 0);
|
||||
stix->_false = stix_instantiate (stix, stix->_false_class STIX_NULL, 0);
|
||||
|
||||
|
115
stix/lib/main.c
Normal file
115
stix/lib/main.c
Normal file
@ -0,0 +1,115 @@
|
||||
#include "stix-prv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void* sys_alloc (stix_mmgr_t* mmgr, stix_size_t size)
|
||||
{
|
||||
return malloc (size);
|
||||
}
|
||||
|
||||
static void* sys_realloc (stix_mmgr_t* mmgr, void* ptr, stix_size_t size)
|
||||
{
|
||||
return realloc (ptr, size);
|
||||
}
|
||||
|
||||
static void sys_free (stix_mmgr_t* mmgr, void* ptr)
|
||||
{
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
static stix_mmgr_t sys_mmgr =
|
||||
{
|
||||
sys_alloc,
|
||||
sys_realloc,
|
||||
sys_free,
|
||||
STIX_NULL
|
||||
};
|
||||
|
||||
static void dump_symbol_table (stix_t* stix)
|
||||
{
|
||||
stix_oow_t i, j;
|
||||
stix_oop_char_t symbol;
|
||||
|
||||
printf ("--------------------------------------------\n");
|
||||
printf ("Stix Symbol Table %lu\n", (unsigned long int)STIX_OBJ_GET_SIZE(stix->symtab->bucket));
|
||||
printf ("--------------------------------------------\n");
|
||||
|
||||
for (i = 0; i < STIX_OBJ_GET_SIZE(stix->symtab->bucket); i++)
|
||||
{
|
||||
symbol = (stix_oop_char_t)stix->symtab->bucket->slot[i];
|
||||
if ((stix_oop_t)symbol != stix->_nil)
|
||||
{
|
||||
printf (" %lu [", (unsigned long int)i);
|
||||
for (j = 0; j < STIX_OBJ_GET_SIZE(symbol); j++)
|
||||
{
|
||||
printf ("%c", symbol->slot[j]);
|
||||
}
|
||||
printf ("]\n");
|
||||
}
|
||||
}
|
||||
printf ("--------------------------------------------\n");
|
||||
}
|
||||
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
stix_t* stix;
|
||||
printf ("Stix 1.0.0 - max named %lu max indexed %lu\n",
|
||||
(unsigned long int)STIX_MAX_NAMED_INSTVARS, (unsigned long int)STIX_MAX_INDEXED_INSTVARS(STIX_MAX_NAMED_INSTVARS));
|
||||
|
||||
|
||||
{
|
||||
stix_oow_t x;
|
||||
|
||||
printf ("%u\n", STIX_BITS_MAX(unsigned int, 5));
|
||||
|
||||
x = STIX_CLASS_SPEC_MAKE (10, 1, STIX_OBJ_TYPE_CHAR);
|
||||
printf ("%lu %lu %lu %lu\n", (unsigned long int)x, (unsigned long int)STIX_OOP_FROM_SMINT(x),
|
||||
(unsigned long int)STIX_CLASS_SPEC_NAMED_INSTVAR(x),
|
||||
(unsigned long int)STIX_CLASS_SPEC_INDEXED_TYPE(x));
|
||||
}
|
||||
|
||||
stix = stix_open (&sys_mmgr, 0, 1000000lu, STIX_NULL);
|
||||
if (!stix)
|
||||
{
|
||||
printf ("cannot open stix\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
stix_oow_t symtab_size = 5000;
|
||||
stix_setoption (stix, STIX_DEFAULT_SYMTAB_SIZE, &symtab_size);
|
||||
stix_setoption (stix, STIX_DEFAULT_SYSDIC_SIZE, &symtab_size);
|
||||
}
|
||||
|
||||
if (stix_ignite(stix) <= -1)
|
||||
{
|
||||
printf ("cannot ignite stix\n");
|
||||
stix_close (stix);
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
stix_char_t x[] = { 'S', 't', 'r', 'i', 'n', 'g', '\0' };
|
||||
stix_char_t y[] = { 'S', 'y', 'm', 'b', 'o', 'l', '\0' };
|
||||
stix_oop_t a, b;
|
||||
|
||||
a = stix_makesymbol (stix, x, 6);
|
||||
b = stix_makesymbol (stix, y, 6);
|
||||
|
||||
printf ("%p %p\n", a, b);
|
||||
}
|
||||
|
||||
dump_symbol_table (stix);
|
||||
stix_gc (stix);
|
||||
dump_symbol_table (stix);
|
||||
|
||||
stix_close (stix);
|
||||
|
||||
#if defined(__BORLANDC__)
|
||||
printf ("Press the enter key...\n");
|
||||
getchar ();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
@ -30,6 +30,10 @@ void* stix_allocbytes (stix_t* stix, stix_size_t size)
|
||||
{
|
||||
stix_uint8_t* ptr;
|
||||
|
||||
#if defined(STIX_DEBUG_GC_1)
|
||||
stix_gc (stix);
|
||||
#endif
|
||||
|
||||
ptr = stix_allocheapmem (stix, stix->curheap, size);
|
||||
if (!ptr && !(stix->option.trait & STIX_NOGC))
|
||||
{
|
||||
@ -135,7 +139,7 @@ stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr,
|
||||
STIX_ASSERT (stix->_nil != STIX_NULL);
|
||||
|
||||
STIX_ASSERT (STIX_OOP_IS_POINTER(_class));
|
||||
/*STIX_ASSERT (STIX_CLASSOF(_class) == stix->_class); */
|
||||
STIX_ASSERT (STIX_CLASSOF(stix, _class) == stix->_class);
|
||||
|
||||
STIX_ASSERT (STIX_OOP_IS_SMINT(((stix_oop_class_t)_class)->spec));
|
||||
spec = STIX_OOP_TO_SMINT(((stix_oop_class_t)_class)->spec);
|
||||
@ -170,15 +174,17 @@ stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr,
|
||||
if (named_instvar > STIX_MAX_NAMED_INSTVARS) goto einval;
|
||||
}
|
||||
|
||||
stix_pushtmp (stix, &_class);
|
||||
|
||||
switch (indexed_type)
|
||||
{
|
||||
case STIX_OBJ_TYPE_OOP:
|
||||
/* class for a variable object.
|
||||
* both the named_instvar-sized part and the variable part are allowed. */
|
||||
/* both the fixed part(named instance variables) and
|
||||
* the variable part(indexed instance variables) are allowed. */
|
||||
oop = stix_allocoopobj(stix, named_instvar + vlen);
|
||||
if (!oop) return STIX_NULL;
|
||||
|
||||
if (vlen > 0)
|
||||
if (vptr && vlen > 0)
|
||||
{
|
||||
stix_oop_oop_t hdr = (stix_oop_oop_t)oop;
|
||||
STIX_MEMCPY (&hdr->slot[named_instvar], vptr, vlen * STIX_SIZEOF(stix_oop_t));
|
||||
@ -186,13 +192,11 @@ stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr,
|
||||
break;
|
||||
|
||||
case STIX_OBJ_TYPE_CHAR:
|
||||
/* variable-char class can't have instance variables */
|
||||
oop = stix_alloccharobj(stix, vptr, vlen);
|
||||
if (!oop) return STIX_NULL;
|
||||
break;
|
||||
|
||||
case STIX_OBJ_TYPE_UINT8:
|
||||
/* variable-byte class can't have instance variables */
|
||||
oop = stix_allocuint8obj(stix, vptr, vlen);
|
||||
if (!oop) return STIX_NULL;
|
||||
break;
|
||||
@ -207,7 +211,9 @@ stix_oop_t stix_instantiate (stix_t* stix, stix_oop_t _class, const void* vptr,
|
||||
return STIX_NULL;
|
||||
}
|
||||
|
||||
oop->_class = _class;
|
||||
STIX_OBJ_SET_CLASS (oop, _class);
|
||||
stix_poptmp (stix);
|
||||
|
||||
return oop;
|
||||
|
||||
|
||||
|
@ -29,6 +29,12 @@
|
||||
|
||||
#include "stix.h"
|
||||
|
||||
/* this is useful for debugging. stix_gc() can be called
|
||||
* while stix has not been fully initialized when this is defined*/
|
||||
#define STIX_SUPPORT_GC_DURING_IGNITION
|
||||
#define STIX_DEBUG_GC_1
|
||||
|
||||
|
||||
#include <stdio.h> /* TODO: delete these header inclusion lines */
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
@ -40,32 +46,10 @@
|
||||
#define STIX_ALIGN(x,y) ((((x) + (y) - 1) / (y)) * (y))
|
||||
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
/* CLASS */
|
||||
/* CLASS SPEC ENCODING */
|
||||
/* ========================================================================= */
|
||||
|
||||
/* The stix_class_t type defines the internal structure of a class object. */
|
||||
struct stix_class_t
|
||||
{
|
||||
STIX_OBJ_HEADER;
|
||||
|
||||
stix_oow_t spec; /* SmallInteger */
|
||||
stix_oop_oop_t instmthds; /* instance methods, MethodDictionary */
|
||||
stix_oop_oop_t classmthds; /* class methods, MethodDictionary */
|
||||
stix_oop_oop_t superclass; /* Another class */
|
||||
|
||||
stix_oop_char_t name; /* Symbol */
|
||||
stix_oop_char_t instvars; /* String or Array? */
|
||||
stix_oop_char_t classvars; /* String or Array? */
|
||||
|
||||
/* indexed part afterwards */
|
||||
};
|
||||
|
||||
|
||||
typedef struct stix_class_t stix_class_t;
|
||||
typedef struct stix_class_t* stix_oop_class_t;
|
||||
|
||||
/*
|
||||
* The spec field of a class object encodes the number of the fixed part
|
||||
* and the type of the indexed part. The fixed part is the number of
|
||||
@ -138,20 +122,6 @@ typedef struct stix_class_t* stix_oop_class_t;
|
||||
*/
|
||||
#define STIX_MAX_INDEXED_INSTVARS(named_instvar) ((~(stix_oow_t)0) - named_instvar)
|
||||
|
||||
|
||||
#define STIX_CLASSOF(stix,oop) \
|
||||
(STIX_OOP_IS_NUMERIC(oop)? \
|
||||
((stix_oop_t)(stix)->cc.numeric[((stix_oow_t)oop&3)-1]): \
|
||||
(oop)->_class)
|
||||
|
||||
/*
|
||||
#define STIX_BYTESOF(stix,oop) \
|
||||
(STIX_OOP_IS_NUMERIC(oop)? \
|
||||
(STIX_SIZEOF(stix_oow_t)): \
|
||||
(STIX_SIZEOF(stix_obj_t) + STIX_ALIGN(((oop)->size + (oop)->extra) * (oop)->unit), STIX_SIZEOF(stix_oop_t)) \
|
||||
)
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -191,6 +161,19 @@ void* stix_allocheapmem (
|
||||
);
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
/* stix.c */
|
||||
/* ========================================================================= */
|
||||
stix_oow_t stix_hashbytes (
|
||||
const stix_uint8_t* ptr,
|
||||
stix_oow_t len
|
||||
);
|
||||
|
||||
stix_oow_t stix_hashchars (
|
||||
const stix_char_t* ptr,
|
||||
stix_size_t len
|
||||
);
|
||||
|
||||
/* ========================================================================= */
|
||||
/* obj.c */
|
||||
/* ========================================================================= */
|
||||
@ -199,6 +182,10 @@ void* stix_allocbytes (
|
||||
stix_size_t size
|
||||
);
|
||||
|
||||
/**
|
||||
* The stix_allocoopobj() function allocates a raw object composed of \a size
|
||||
* pointer fields excluding the header.
|
||||
*/
|
||||
stix_oop_t stix_allocoopobj (
|
||||
stix_t* stix,
|
||||
stix_oow_t size
|
||||
@ -222,6 +209,34 @@ stix_oop_t stix_allocuint16obj (
|
||||
stix_oow_t len
|
||||
);
|
||||
|
||||
/* ========================================================================= */
|
||||
/* sym.c */
|
||||
/* ========================================================================= */
|
||||
stix_oop_t stix_makesymbol (
|
||||
stix_t* stix,
|
||||
const stix_char_t* ptr,
|
||||
stix_oow_t len
|
||||
);
|
||||
|
||||
stix_oop_t stix_findsymbol (
|
||||
stix_t* stix,
|
||||
const stix_char_t* ptr,
|
||||
stix_oow_t len
|
||||
);
|
||||
|
||||
/* ========================================================================= */
|
||||
/* dic.c */
|
||||
/* ========================================================================= */
|
||||
stix_oop_t stix_putatsysdic (
|
||||
stix_t* stix,
|
||||
stix_oop_t key,
|
||||
stix_oop_t value
|
||||
);
|
||||
|
||||
stix_oop_t stix_getatsysdic (
|
||||
stix_t* stix,
|
||||
stix_oop_t key
|
||||
);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
142
stix/lib/stix.c
Normal file
142
stix/lib/stix.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2014-2015 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stix-prv.h"
|
||||
|
||||
|
||||
stix_t* stix_open (stix_mmgr_t* mmgr, stix_size_t xtnsize, stix_size_t heapsize, stix_errnum_t* errnum)
|
||||
{
|
||||
stix_t* stix;
|
||||
|
||||
stix = STIX_MMGR_ALLOC (mmgr, STIX_SIZEOF(*stix) + xtnsize);
|
||||
if (stix)
|
||||
{
|
||||
if (stix_init(stix, mmgr, heapsize) <= -1)
|
||||
{
|
||||
if (errnum) *errnum = stix->errnum;
|
||||
STIX_MMGR_FREE (mmgr, stix);
|
||||
stix = STIX_NULL;
|
||||
}
|
||||
else STIX_MEMSET (stix + 1, 0, xtnsize);
|
||||
}
|
||||
else if (errnum)
|
||||
{
|
||||
*errnum = STIX_ENOMEM;
|
||||
}
|
||||
|
||||
return stix;
|
||||
}
|
||||
|
||||
void stix_close (stix_t* stix)
|
||||
{
|
||||
stix_fini (stix);
|
||||
STIX_MMGR_FREE (stix->mmgr, stix);
|
||||
}
|
||||
|
||||
int stix_init (stix_t* stix, stix_mmgr_t* mmgr, stix_size_t heapsz)
|
||||
{
|
||||
STIX_MEMSET (stix, 0, STIX_SIZEOF(*stix));
|
||||
stix->mmgr = mmgr;
|
||||
|
||||
/*stix->permheap = stix_makeheap (stix, what is the best size???);
|
||||
if (!stix->curheap) goto oops; */
|
||||
stix->curheap = stix_makeheap (stix, heapsz);
|
||||
if (!stix->curheap) goto oops;
|
||||
stix->newheap = stix_makeheap (stix, heapsz);
|
||||
if (!stix->newheap) goto oops;
|
||||
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
if (stix->newheap) stix_killheap (stix, stix->newheap);
|
||||
if (stix->curheap) stix_killheap (stix, stix->curheap);
|
||||
if (stix->permheap) stix_killheap (stix, stix->permheap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void stix_fini (stix_t* stix)
|
||||
{
|
||||
stix_killheap (stix, stix->newheap);
|
||||
stix_killheap (stix, stix->curheap);
|
||||
stix_killheap (stix, stix->permheap);
|
||||
}
|
||||
|
||||
int stix_setoption (stix_t* stix, stix_option_t id, const void* value)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case STIX_TRAIT:
|
||||
stix->option.trait = *(const int*)value;
|
||||
return 0;
|
||||
|
||||
case STIX_DEFAULT_SYMTAB_SIZE:
|
||||
stix->option.default_symtab_size = *(stix_oow_t*)value;
|
||||
|
||||
case STIX_DEFAULT_SYSDIC_SIZE:
|
||||
stix->option.default_sysdic_size = *(stix_oow_t*)value;
|
||||
}
|
||||
|
||||
stix->errnum = STIX_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int stix_getoption (stix_t* stix, stix_option_t id, void* value)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case STIX_TRAIT:
|
||||
*(int*)value = stix->option.trait;
|
||||
return 0;
|
||||
|
||||
case STIX_DEFAULT_SYMTAB_SIZE:
|
||||
*(stix_oow_t*)value = stix->option.default_symtab_size;
|
||||
|
||||
case STIX_DEFAULT_SYSDIC_SIZE:
|
||||
*(stix_oow_t*)value = stix->option.default_sysdic_size;
|
||||
};
|
||||
|
||||
stix->errnum = STIX_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
stix_oow_t stix_hashbytes (const stix_uint8_t* ptr, stix_oow_t len)
|
||||
{
|
||||
stix_oow_t h = 0;
|
||||
const stix_uint8_t* bp, * be;
|
||||
|
||||
bp = ptr; be = bp + len;
|
||||
while (bp < be) h = h * 31 + *bp++;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
stix_oow_t stix_hashchars (const stix_char_t* ptr, stix_size_t len)
|
||||
{
|
||||
return stix_hashbytes ((const stix_uint8_t *)ptr, len * STIX_SIZEOF(*ptr));
|
||||
}
|
||||
|
||||
|
245
stix/lib/stix.h
245
stix/lib/stix.h
@ -188,7 +188,9 @@ typedef enum stix_errnum_t stix_errnum_t;
|
||||
|
||||
enum stix_option_t
|
||||
{
|
||||
STIX_TRAIT
|
||||
STIX_TRAIT,
|
||||
STIX_DEFAULT_SYMTAB_SIZE,
|
||||
STIX_DEFAULT_SYSDIC_SIZE
|
||||
};
|
||||
typedef enum stix_option_t stix_option_t;
|
||||
|
||||
@ -383,53 +385,6 @@ enum stix_code_t
|
||||
typedef enum stix_code_t stix_code_t;
|
||||
|
||||
|
||||
typedef struct stix_heap_t stix_heap_t;
|
||||
|
||||
struct stix_heap_t
|
||||
{
|
||||
stix_uint8_t* base; /* start of a heap */
|
||||
stix_uint8_t* limit; /* end of a heap */
|
||||
stix_uint8_t* ptr; /* next allocation pointer */
|
||||
};
|
||||
|
||||
typedef struct stix_t stix_t;
|
||||
|
||||
struct stix_t
|
||||
{
|
||||
stix_mmgr_t* mmgr;
|
||||
stix_errnum_t errnum;
|
||||
|
||||
struct
|
||||
{
|
||||
int trait;
|
||||
} option;
|
||||
|
||||
/* ========================= */
|
||||
|
||||
stix_heap_t* permheap;
|
||||
stix_heap_t* curheap;
|
||||
stix_heap_t* newheap;
|
||||
|
||||
/* ========================= */
|
||||
|
||||
stix_oop_t _nil; /* pointer to the nil object */
|
||||
stix_oop_t _true;
|
||||
stix_oop_t _false;
|
||||
|
||||
stix_oop_oop_t root; /* pointer to the system dictionary */
|
||||
stix_oop_oop_t symtab; /* system-wide symbol table */
|
||||
|
||||
struct
|
||||
{
|
||||
stix_oop_oop_t array;
|
||||
stix_oop_oop_t association;
|
||||
/*stix_oop_oop_t metaclass;*/
|
||||
stix_oop_oop_t string;
|
||||
stix_oop_oop_t symbol;
|
||||
stix_oop_oop_t sysdic;
|
||||
stix_oop_oop_t numeric[2]; /* [0]: smint [1]: character */
|
||||
} cc; /* common kernel classes */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
@ -453,6 +408,7 @@ struct stix_t
|
||||
|
||||
#define STIX_OOP_IS_NUMERIC(oop) (((stix_oow_t)oop) & (STIX_OOP_TAG_SMINT | STIX_OOP_TAG_CHAR))
|
||||
#define STIX_OOP_IS_POINTER(oop) (!STIX_OOP_IS_NUMERIC(oop))
|
||||
#define STIX_OOP_GET_TAG(oop) (((stix_oow_t)oop) & STIX_LBMASK(stix_oow_t, STIX_OOP_TAG_BITS))
|
||||
|
||||
#define STIX_OOP_IS_SMINT(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_SMINT)
|
||||
#define STIX_OOP_IS_CHAR(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_CHAR)
|
||||
@ -499,7 +455,7 @@ typedef enum stix_obj_type_t stix_obj_type_t;
|
||||
* moved: 0 or 1. used by GC.
|
||||
*
|
||||
* _size: the number of payload items in an object.
|
||||
* it doesn't include the header size.
|
||||
* it doesn't include the header size.
|
||||
*
|
||||
* The total number of bytes occupied by an object can be calculated
|
||||
* with this fomula:
|
||||
@ -528,15 +484,19 @@ typedef enum stix_obj_type_t stix_obj_type_t;
|
||||
#define STIX_OBJ_GET_FLAGS_TYPE(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_UNIT_BITS + STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_TYPE_BITS)
|
||||
#define STIX_OBJ_GET_FLAGS_UNIT(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_UNIT_BITS)
|
||||
#define STIX_OBJ_GET_FLAGS_EXTRA(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_EXTRA_BITS)
|
||||
#define STIX_OBJ_GET_FLAGS_KERNEL(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_UNIT_BITS), STIX_OBJ_FLAGS_KERNEL_BITS)
|
||||
#define STIX_OBJ_GET_FLAGS_KERNEL(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_KERNEL_BITS)
|
||||
#define STIX_OBJ_GET_FLAGS_MOVED(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, 0, STIX_OBJ_FLAGS_MOVED_BITS)
|
||||
|
||||
#define STIX_OBJ_SET_FLAGS_TYPE(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_UNIT_BITS + STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_TYPE_BITS, v)
|
||||
#define STIX_OBJ_SET_FLAGS_UNIT(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_UNIT_BITS, v)
|
||||
#define STIX_OBJ_SET_FLAGS_EXTRA(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_EXTRA_BITS, v)
|
||||
#define STIX_OBJ_SET_FLAGS_KERNEL(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_UNIT_BITS), STIX_OBJ_FLAGS_KERNEL_BITS, v)
|
||||
#define STIX_OBJ_SET_FLAGS_KERNEL(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_KERNEL_BITS, v)
|
||||
#define STIX_OBJ_SET_FLAGS_MOVED(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, 0, STIX_OBJ_FLAGS_MOVED_BITS, v)
|
||||
|
||||
#define STIX_OBJ_GET_SIZE(oop) ((oop)->_size)
|
||||
#define STIX_OBJ_GET_CLASS(oop) ((oop)->_class)
|
||||
#define STIX_OBJ_SET_CLASS(oop,c) ((oop)->_class = (c))
|
||||
|
||||
/* this macro doesn't check the range of the actual value.
|
||||
* make sure that the value of each bit fields given fall within the number
|
||||
* of defined bits */
|
||||
@ -582,8 +542,48 @@ struct stix_obj_uint16_t
|
||||
stix_uint16_t slot[1];
|
||||
};
|
||||
|
||||
#if 0
|
||||
#define STIX_CLASS_NAMED_INSTVARS 8
|
||||
struct stix_class_t
|
||||
{
|
||||
STIX_OBJ_HEADER;
|
||||
|
||||
stix_oop_t spec; /* SmallInteger */
|
||||
stix_oop_t superclass; /* Another class */
|
||||
stix_oop_t subclasses; /* Array of subclasses */
|
||||
stix_oop_char_t name; /* Symbol */
|
||||
stix_oop_char_t instvars; /* String or Array? */
|
||||
stix_oop_char_t classvars; /* String or Array? */
|
||||
|
||||
stix_oop_oop_t instmthds; /* instance methods, MethodDictionary */
|
||||
stix_oop_oop_t classmthds; /* class methods, MethodDictionary */
|
||||
|
||||
/* indexed part afterwards */
|
||||
stix_oop_t classvar[1]; /* most classes have not class variables. better to be 0 */
|
||||
};
|
||||
typedef struct stix_class_t stix_class_t;
|
||||
typedef struct stix_class_t* stix_oop_class_t;
|
||||
|
||||
#define STIX_SET_NAMED_INSTVARS 2
|
||||
struct stix_set_t
|
||||
{
|
||||
STIX_OBJ_HEADER;
|
||||
stix_oop_t tally; /* SmallInteger */
|
||||
stix_oop_oop_t bucket; /* Array */
|
||||
};
|
||||
typedef struct stix_set_t stix_set_t;
|
||||
typedef struct stix_set_t* stix_oop_set_t;
|
||||
|
||||
#define STIX_ASSOCIATION_NAMED_INSTVARS 2
|
||||
struct stix_association_t
|
||||
{
|
||||
STIX_OBJ_HEADER;
|
||||
stix_oop_t key;
|
||||
stix_oop_t value;
|
||||
};
|
||||
typedef struct stix_association_t stix_association_t;
|
||||
typedef struct stix_association_t* stix_oop_association_t;
|
||||
|
||||
#if 0
|
||||
/* -----------------------------------------
|
||||
* class structures for classes known to VM
|
||||
* ----------------------------------------- */
|
||||
@ -653,62 +653,75 @@ enum stix_class_desc_t
|
||||
STIX_SYSDIC_BUCKET = STIX_DICTIONARY_BUCKET,
|
||||
STIX_SYSDIC_SIZE = STIX_DICTIONARY_SIZE
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct stix_kcinfo_t
|
||||
{
|
||||
const stix_char_t* name;
|
||||
int super;
|
||||
int fixed; /* the number of fixed fields */
|
||||
int vtype; /* variable class type */
|
||||
|
||||
int nivars; /* instance variables */
|
||||
stix_cstr_t ivars[10];
|
||||
|
||||
int ncvars; /* class variables */
|
||||
stix_cstr_t cvars[10];
|
||||
|
||||
int ncivars; /* class instance variables */
|
||||
stix_cstr_t civars[10];
|
||||
};
|
||||
|
||||
typedef struct stix_kcinfo_t stix_kcinfo_t;
|
||||
|
||||
enum stix_kc_t
|
||||
{
|
||||
STIX_VM_KC_OBJECT,
|
||||
STIX_VM_KC_UNDEFINED_OBJECT,
|
||||
STIX_VM_KC_BEHAVIOR,
|
||||
STIX_VM_KC_CLASS,
|
||||
STIX_VM_KC_METACLASS,
|
||||
STIX_VM_KC_BLOCK,
|
||||
STIX_VM_KC_BOOLEAN,
|
||||
STIX_VM_KC_TRUE,
|
||||
STIX_VM_KC_FALSE,
|
||||
STIX_VM_KC_CONTEXT,
|
||||
STIX_VM_KC_METHOD,
|
||||
STIX_VM_KC_MAGNITUDE,
|
||||
STIX_VM_KC_ASSOCIATION,
|
||||
STIX_VM_KC_CHARACTER,
|
||||
STIX_VM_KC_NUMBER,
|
||||
STIX_VM_KC_INTEGER,
|
||||
STIX_VM_KC_SMALL_INTEGER,
|
||||
STIX_VM_KC_LARGE_INTEGER,
|
||||
STIX_VM_KC_COLLECTION,
|
||||
STIX_VM_KC_INDEXED_COLLECTION,
|
||||
STIX_VM_KC_ARRAY,
|
||||
STIX_VM_KC_BYTE_ARRAY,
|
||||
STIX_VM_KC_SYMBOL_TABLE,
|
||||
STIX_VM_KC_DICTIONARY,
|
||||
STIX_VM_KC_SYSTEM_DICTIONARY,
|
||||
STIX_VM_KC_STRING,
|
||||
STIX_VM_KC_SYMBOL,
|
||||
|
||||
STIX_VM_KC_MAX /* indicate the number of kernel classes */
|
||||
};
|
||||
#endif
|
||||
|
||||
#define STIX_CLASSOF(stix,oop) ( \
|
||||
STIX_OOP_IS_SMINT(oop)? (stix)->_small_integer: \
|
||||
STIX_OOP_IS_CHAR(oop)? (stix)->_character: (oop)->_class \
|
||||
)
|
||||
|
||||
/*
|
||||
#define STIX_BYTESOF(stix,oop) \
|
||||
(STIX_OOP_IS_NUMERIC(oop)? \
|
||||
(STIX_SIZEOF(stix_oow_t)): \
|
||||
(STIX_SIZEOF(stix_obj_t) + STIX_ALIGN(((oop)->size + (oop)->extra) * (oop)->unit), STIX_SIZEOF(stix_oop_t)) \
|
||||
)
|
||||
*/
|
||||
|
||||
typedef struct stix_heap_t stix_heap_t;
|
||||
|
||||
struct stix_heap_t
|
||||
{
|
||||
stix_uint8_t* base; /* start of a heap */
|
||||
stix_uint8_t* limit; /* end of a heap */
|
||||
stix_uint8_t* ptr; /* next allocation pointer */
|
||||
};
|
||||
|
||||
typedef struct stix_t stix_t;
|
||||
|
||||
struct stix_t
|
||||
{
|
||||
stix_mmgr_t* mmgr;
|
||||
stix_errnum_t errnum;
|
||||
|
||||
struct
|
||||
{
|
||||
int trait;
|
||||
stix_oow_t default_symtab_size;
|
||||
stix_oow_t default_sysdic_size;
|
||||
} option;
|
||||
|
||||
/* ========================= */
|
||||
|
||||
stix_heap_t* permheap; /* TODO: put kernel objects to here */
|
||||
stix_heap_t* curheap;
|
||||
stix_heap_t* newheap;
|
||||
|
||||
/* ========================= */
|
||||
stix_oop_t _nil; /* pointer to the nil object */
|
||||
stix_oop_t _true;
|
||||
stix_oop_t _false;
|
||||
|
||||
stix_oop_t _stix; /* Stix */
|
||||
stix_oop_t _nil_object; /* NilObject */
|
||||
stix_oop_t _class; /* Class */
|
||||
stix_oop_t _object; /* Object */
|
||||
stix_oop_t _symbol; /* Symbol */
|
||||
stix_oop_t _array; /* Array */
|
||||
stix_oop_t _symbol_set; /* SymbolSet */
|
||||
stix_oop_t _system_dictionary; /* SystemDictionary */
|
||||
stix_oop_t _association; /* Association */
|
||||
stix_oop_t _character; /* Character */
|
||||
stix_oop_t _small_integer; /* SmallInteger */
|
||||
|
||||
stix_oop_set_t symtab; /* system-wide symbol table. instance of SymbolSet */
|
||||
stix_oop_set_t sysdic; /* system dictionary. instance of SystemDictionary */
|
||||
|
||||
stix_oop_t* tmp_stack[100]; /* stack for temporaries */
|
||||
stix_oow_t tmp_count;
|
||||
};
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -796,8 +809,6 @@ STIX_EXPORT stix_oop_t stix_instantiate (
|
||||
stix_oow_t vlen
|
||||
);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The stix_ignite() function creates key initial objects.
|
||||
*/
|
||||
@ -805,6 +816,24 @@ STIX_EXPORT int stix_ignite (
|
||||
stix_t* stix
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Temporary OOP management
|
||||
*/
|
||||
STIX_EXPORT void stix_pushtmp (
|
||||
stix_t* stix,
|
||||
stix_oop_t* oop_ptr
|
||||
);
|
||||
|
||||
STIX_EXPORT void stix_poptmp (
|
||||
stix_t* stix
|
||||
);
|
||||
|
||||
STIX_EXPORT void stix_poptmps (
|
||||
stix_t* stix,
|
||||
stix_oow_t count
|
||||
);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
151
stix/lib/sym.c
Normal file
151
stix/lib/sym.c
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2014-2015 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stix-prv.h"
|
||||
|
||||
static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t old_bucket)
|
||||
{
|
||||
stix_oop_oop_t new_bucket;
|
||||
stix_oow_t oldsz, newsz, index;
|
||||
stix_oop_char_t symbol;
|
||||
|
||||
/* TODO: derive a better growth size */
|
||||
new_bucket = (stix_oop_oop_t)stix_instantiate (stix, stix->_array, STIX_NULL, STIX_OBJ_GET_SIZE(old_bucket) * 2);
|
||||
if (!new_bucket) return STIX_NULL;
|
||||
|
||||
oldsz = STIX_OBJ_GET_SIZE(old_bucket);
|
||||
newsz = STIX_OBJ_GET_SIZE(new_bucket);
|
||||
|
||||
while (oldsz > 0)
|
||||
{
|
||||
symbol = (stix_oop_char_t)old_bucket->slot[--oldsz];
|
||||
if ((stix_oop_t)symbol != stix->_nil)
|
||||
{
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,symbol) == stix->_symbol);
|
||||
/*STIX_ASSERT (sym->size > 0);*/
|
||||
|
||||
index = stix_hashchars(symbol->slot, STIX_OBJ_GET_SIZE(symbol)) % newsz;
|
||||
while (new_bucket->slot[index] != stix->_nil)
|
||||
index = (index + 1) % newsz;
|
||||
new_bucket->slot[index] = (stix_oop_t)symbol;
|
||||
}
|
||||
}
|
||||
|
||||
return new_bucket;
|
||||
}
|
||||
|
||||
static stix_oop_t find_or_make_symbol (stix_t* stix, const stix_char_t* ptr, stix_oow_t len, int create)
|
||||
{
|
||||
stix_oow_t index, tally;
|
||||
stix_oop_char_t symbol;
|
||||
|
||||
STIX_ASSERT (len > 0);
|
||||
if (len <= 0)
|
||||
{
|
||||
/* i don't allow an empty symbol name */
|
||||
stix->errnum = STIX_EINVAL;
|
||||
return STIX_NULL;
|
||||
}
|
||||
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,stix->symtab->bucket) == stix->_array);
|
||||
index = stix_hashchars(ptr, len) % STIX_OBJ_GET_SIZE(stix->symtab->bucket);
|
||||
|
||||
/* find a matching symbol in the open-addressed symbol table */
|
||||
while (stix->symtab->bucket->slot[index] != stix->_nil)
|
||||
{
|
||||
symbol = (stix_oop_char_t)stix->symtab->bucket->slot[index];
|
||||
STIX_ASSERT (STIX_CLASSOF(stix,symbol) == (stix_oop_t)stix->_symbol);
|
||||
|
||||
if (len == STIX_OBJ_GET_SIZE(symbol))
|
||||
{
|
||||
stix_oow_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (ptr[i] != symbol->slot[i]) goto not_equal;
|
||||
}
|
||||
return (stix_oop_t)symbol;
|
||||
}
|
||||
|
||||
not_equal:
|
||||
index = (index + 1) % STIX_OBJ_GET_SIZE(stix->symtab->bucket);
|
||||
}
|
||||
|
||||
if (!create)
|
||||
{
|
||||
/*
|
||||
stix->errnum = STIX_ENOENT;
|
||||
return STIX_NULL;
|
||||
*/
|
||||
return stix->_nil;
|
||||
}
|
||||
|
||||
tally = STIX_OOP_TO_SMINT(stix->symtab->tally);
|
||||
if (tally + 1 >= STIX_OBJ_GET_SIZE(stix->symtab->bucket))
|
||||
{
|
||||
stix_oop_oop_t bucket;
|
||||
|
||||
/* TODO: make the growth policy configurable instead of growing
|
||||
it just before it gets full. The polcy can be grow it
|
||||
if it's 70% full */
|
||||
|
||||
/* Enlarge the symbol table before it gets full to
|
||||
* make sure that it has at least one free slot left
|
||||
* after having added a new symbol. this is to help
|
||||
* traversal end at a _nil slot if no entry is found. */
|
||||
bucket = expand_bucket (stix, stix->symtab->bucket);
|
||||
if (!bucket) return STIX_NULL;
|
||||
|
||||
stix->symtab->bucket = bucket;
|
||||
|
||||
/* recalculate the index for the expanded bucket */
|
||||
index = stix_hashchars(ptr, len) % STIX_OBJ_GET_SIZE(stix->symtab->bucket);
|
||||
|
||||
while (stix->symtab->bucket->slot[index] != stix->_nil)
|
||||
index = (index + 1) % STIX_OBJ_GET_SIZE(stix->symtab->bucket);
|
||||
}
|
||||
|
||||
/* create a new symbol since it isn't found in the symbol table */
|
||||
symbol = (stix_oop_char_t)stix_instantiate (stix, stix->_symbol, ptr, len);
|
||||
if (symbol)
|
||||
{
|
||||
stix->symtab->tally = STIX_OOP_FROM_SMINT(tally + 1);
|
||||
stix->symtab->bucket->slot[index] = (stix_oop_t)symbol;
|
||||
}
|
||||
|
||||
return (stix_oop_t)symbol;
|
||||
}
|
||||
|
||||
stix_oop_t stix_makesymbol (stix_t* stix, const stix_char_t* ptr, stix_oow_t len)
|
||||
{
|
||||
return find_or_make_symbol (stix, ptr, len, 1);
|
||||
}
|
||||
|
||||
stix_oop_t stix_findsymbol (stix_t* stix, const stix_char_t* ptr, stix_oow_t len)
|
||||
{
|
||||
return find_or_make_symbol (stix, ptr, len, 0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user