added many lines of code for initial loading
This commit is contained in:
		
							
								
								
									
										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); | ||||
| } | ||||
							
								
								
									
										116
									
								
								stix/lib/gc.c
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								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,7 +135,7 @@ 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; | ||||
| @ -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->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)); | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										243
									
								
								stix/lib/stix.h
									
									
									
									
									
								
							
							
						
						
									
										243
									
								
								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) | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user