| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  |  * $Id: dict.c,v 1.11 2007-03-22 11:19:28 bacon Exp $ | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | #include <ase/stx/dict.h>
 | 
					
						
							|  |  |  | #include <ase/stx/object.h>
 | 
					
						
							|  |  |  | #include <ase/stx/misc.h>
 | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-11 10:18:35 +00:00
										 |  |  | /* NOTE:
 | 
					
						
							|  |  |  |  * The code here implements SystemDictionary whose key is always a symbol. | 
					
						
							|  |  |  |  * Dictionary, on the contrary, can accept any object as a key. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | ase_word_t __new_association ( | 
					
						
							|  |  |  | 	ase_stx_t* stx, ase_word_t key, ase_word_t value) | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_word_t x; | 
					
						
							| 
									
										
										
										
											2005-07-19 15:00:09 +00:00
										 |  |  | #ifdef __GNUC__
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_word_t data[2] = { key, value }; | 
					
						
							| 
									
										
										
										
											2005-07-19 15:00:09 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_word_t data[2]; | 
					
						
							| 
									
										
										
										
											2005-07-19 15:00:09 +00:00
										 |  |  | 	data[0] = key; | 
					
						
							|  |  |  | 	data[1] = value; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	x = ase_stx_alloc_word_object ( | 
					
						
							|  |  |  | 		stx, data, ASE_STX_ASSOCIATION_SIZE, ASE_NULL, 0); | 
					
						
							|  |  |  | 	ASE_STX_CLASS(stx,x) = stx->class_association; | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 	return x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | static ase_word_t __dict_find_slot ( | 
					
						
							|  |  |  | 	ase_stx_t* stx, ase_word_t dict, ase_word_t key) | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_word_t size, hash, index, assoc, symbol; | 
					
						
							|  |  |  | 	ase_stx_word_object_t* dict_obj; | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_assert (!ASE_STX_IS_SMALLINT(dict) && | 
					
						
							|  |  |  | 	           ASE_STX_IS_WORD_OBJECT(stx, dict)); | 
					
						
							|  |  |  | 	ase_assert (dict == stx->smalltalk ||  | 
					
						
							|  |  |  | 	           ase_stx_classof(stx,dict) == stx->class_system_dictionary); | 
					
						
							|  |  |  | 	ase_assert (ase_stx_classof(stx,key) == stx->class_symbol); | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	size = ASE_STX_SIZE(stx,dict); | 
					
						
							|  |  |  | 	hash = ase_stx_hash_object(stx, key);  | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 	/* consider tally, the only instance variable of a system dictionary */ | 
					
						
							|  |  |  | 	index = hash % (size - 1) + 1; | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	dict_obj = ASE_STX_WORD_OBJECT(stx,dict); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	while (1) { | 
					
						
							|  |  |  | 		assoc = dict_obj->data[index]; | 
					
						
							|  |  |  | 		if (assoc == stx->nil) break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 		symbol = ASE_STX_WORD_AT(stx,assoc,ASE_STX_ASSOCIATION_KEY); | 
					
						
							|  |  |  | 		ase_assert (ase_stx_classof(stx,symbol) == stx->class_symbol); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-11 10:11:26 +00:00
										 |  |  | 		/* NOTE:
 | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 		 * shallow comparison is enough for identity check  | 
					
						
							| 
									
										
										
										
											2005-08-11 10:18:35 +00:00
										 |  |  | 		 * because a symbol can just be a key of a system dictionary | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 		if (ase_strxncmp( | 
					
						
							|  |  |  | 			ASE_STX_DATA(stx,key), ASE_STX_SIZE(stx,key), | 
					
						
							|  |  |  | 			ASE_STX_DATA(stx,symbol), ASE_STX_SIZE(stx,symbol)) == 0) break; | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* consider tally here too */	 | 
					
						
							|  |  |  | 		index = index % (size - 1) + 1; | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 	return index; | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | static void __grow_dict (ase_stx_t* stx, ase_word_t dict) | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_word_t new, size, index, assoc; | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-08-11 10:11:26 +00:00
										 |  |  | 	/* WARNING:
 | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 	 * if this assertion fails, adjust the initial size of the  | 
					
						
							|  |  |  | 	 * system dictionary. i don't want this function to be called | 
					
						
							|  |  |  | 	 * during the bootstrapping. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_assert (stx->class_system_dictionary != stx->nil); | 
					
						
							|  |  |  | 	ase_assert (ase_stx_classof(stx,dict) == stx->class_system_dictionary); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	size = ASE_STX_SIZE(stx,dict); | 
					
						
							|  |  |  | 	new = ase_stx_instantiate (stx,  | 
					
						
							|  |  |  | 		ASE_STX_CLASS(stx,dict), ASE_NULL, ASE_NULL, (size - 1) * 2);  | 
					
						
							|  |  |  | 	ASE_STX_WORD_AT(stx,new,0) = ASE_STX_TO_SMALLINT(0);		 | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (index = 1; index < size; index++) { | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 		assoc = ASE_STX_WORD_AT(stx,dict,index); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 		if (assoc == stx->nil) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 		ase_stx_dict_put (stx, new,  | 
					
						
							|  |  |  | 			ASE_STX_WORD_AT(stx,assoc,ASE_STX_ASSOCIATION_KEY), | 
					
						
							|  |  |  | 			ASE_STX_WORD_AT(stx,assoc,ASE_STX_ASSOCIATION_VALUE)); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-08-11 10:11:26 +00:00
										 |  |  | 	/* TODO: explore if dict can be immediately destroyed. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_assert (ase_sizeof(ase_stx_object_t*) == ase_sizeof(ase_uint_t)); | 
					
						
							|  |  |  | 	ASE_SWAP (ASE_STX_OBJECT(stx,dict), | 
					
						
							|  |  |  | 	         ASE_STX_OBJECT(stx,new), | 
					
						
							|  |  |  | 	         ase_stx_object_t*, ase_uint_t); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | ase_word_t ase_stx_dict_lookup ( | 
					
						
							|  |  |  | 	ase_stx_t* stx, ase_word_t dict, const ase_char_t* key) | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_word_t size, hash, index, assoc, symbol; | 
					
						
							|  |  |  | 	ase_stx_word_object_t* dict_obj; | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_assert (!ASE_STX_IS_SMALLINT(dict) && | 
					
						
							|  |  |  | 	           ASE_STX_IS_WORD_OBJECT(stx, dict)); | 
					
						
							|  |  |  | 	ase_assert (dict == stx->smalltalk ||  | 
					
						
							|  |  |  | 	           ase_stx_classof(stx,dict) == stx->class_system_dictionary); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	size = ASE_STX_SIZE(stx,dict); | 
					
						
							|  |  |  | 	hash = ase_stx_hash(key, ase_strlen(key) * ase_sizeof(ase_char_t)); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* consider tally, the only instance variable of a system dictionary */ | 
					
						
							|  |  |  | 	index = hash % (size - 1) + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	dict_obj = ASE_STX_WORD_OBJECT(stx,dict); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	while (1) { | 
					
						
							|  |  |  | 		assoc = dict_obj->data[index]; | 
					
						
							|  |  |  | 		if (assoc == stx->nil) break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 		symbol = ASE_STX_WORD_AT(stx,assoc,ASE_STX_ASSOCIATION_KEY); | 
					
						
							|  |  |  | 		ase_assert (ase_stx_classof(stx,symbol) == stx->class_symbol); | 
					
						
							| 
									
										
										
										
											2005-07-19 15:52:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 		if (ase_strxcmp (ASE_STX_DATA(stx,symbol), | 
					
						
							|  |  |  | 			ASE_STX_SIZE(stx,symbol), key) == 0) break; | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* consider tally here too */	 | 
					
						
							|  |  |  | 		index = index % (size - 1) + 1; | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	return ASE_STX_WORD_AT(stx,dict,index); | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | ase_word_t ase_stx_dict_get (ase_stx_t* stx, ase_word_t dict, ase_word_t key) | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	return ASE_STX_WORD_AT(stx,dict,__dict_find_slot(stx, dict, key)); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | ase_word_t ase_stx_dict_put ( | 
					
						
							|  |  |  | 	ase_stx_t* stx, ase_word_t dict, ase_word_t key, ase_word_t value) | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_word_t slot, capa, tally, assoc; | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 	/* the dictionary must have at least one slot excluding tally */ | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_assert (ASE_STX_SIZE(stx,dict) > 1); | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	capa = ASE_STX_SIZE(stx,dict) - 1; | 
					
						
							|  |  |  | 	tally = ASE_STX_FROM_SMALLINT(ASE_STX_WORD_AT(stx,dict,0)); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 	if (capa <= tally + 1) { | 
					
						
							| 
									
										
										
										
											2005-08-11 09:57:54 +00:00
										 |  |  | 		__grow_dict (stx, dict); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 		/* refresh tally */ | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 		tally = ASE_STX_FROM_SMALLINT(ASE_STX_WORD_AT(stx,dict,0)); | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	slot = __dict_find_slot (stx, dict, key); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	assoc = ASE_STX_WORD_AT(stx,dict,slot); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 	if (assoc == stx->nil) { | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 		ASE_STX_WORD_AT(stx,dict,slot) =  | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 			__new_association (stx, key, value); | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 		ASE_STX_WORD_AT(stx,dict,0) = ASE_STX_TO_SMALLINT(tally + 1); | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	else ASE_STX_WORD_AT(stx,assoc,ASE_STX_ASSOCIATION_VALUE) = value; | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	return ASE_STX_WORD_AT(stx,dict,slot); | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | void ase_stx_dict_traverse ( | 
					
						
							|  |  |  | 	ase_stx_t* stx, ase_word_t dict,  | 
					
						
							|  |  |  | 	void (*func) (ase_stx_t*,ase_word_t,void*), void* data) | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 	ase_word_t index, assoc; | 
					
						
							|  |  |  | 	ase_word_t size = ASE_STX_SIZE(stx,dict); | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 	for (index = 1; index < size; index++) { | 
					
						
							| 
									
										
										
										
											2007-03-22 11:19:28 +00:00
										 |  |  | 		assoc = ASE_STX_WORD_AT(stx,dict,index); | 
					
						
							| 
									
										
										
										
											2005-07-19 12:08:04 +00:00
										 |  |  | 		if (assoc == stx->nil) continue; | 
					
						
							|  |  |  | 		func (stx, assoc, data); | 
					
						
							| 
									
										
										
										
											2005-07-18 11:53:01 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |