rev 540 - in trunk: . include/prothon modules/Prosist src

SVN User <[email protected]> Sun, 23 May 2004 21:48:21 -0400
Newsgroups gmane.comp.lang.prothon.cvs
Message-ID <[email protected]>
Author: mark
Date: 2004-05-23 21:48:19 -0400 (Sun, 23 May 2004)
New Revision: 540

Added:
   trunk/src/builtins-attrdict.c
Modified:
   trunk/STATUS.txt
   trunk/include/prothon/prothon.h
   trunk/include/prothon/prothon_dll.h
   trunk/modules/Prosist/Prosist.c
   trunk/src/builtins-core.c
   trunk/src/builtins-dict.c
   trunk/src/object.c
   trunk/src/object.h
   trunk/src/src.vcproj
Log:
middle of working on new attrs_, old attrs() is broken

Modified: trunk/STATUS.txt
===================================================================
--- trunk/STATUS.txt	2004-05-23 23:51:18 UTC (rev 539)
+++ trunk/STATUS.txt	2004-05-24 01:48:19 UTC (rev 540)
@@ -49,12 +49,14 @@
 --- improve torture with list and dict tortures, random walk against new end
 
 
------------------------ DOCS TO-DO ------------------------
+----------------------- TUTORIAL TO-DO ------------------------
 
+	attrs_
+	ante
+	modules
 	Inheriting from binary objects, uninitialized objects
 	print statement
 	import
-	modules
 	packages 
 	list comprehensions
 	try/finally

Modified: trunk/include/prothon/prothon.h
===================================================================
--- trunk/include/prothon/prothon.h	2004-05-23 23:51:18 UTC (rev 539)
+++ trunk/include/prothon/prothon.h	2004-05-24 01:48:19 UTC (rev 540)
@@ -545,11 +545,12 @@
 
 // ATTR_xxx: functions to scan attribute table
 // key is the unique integer assigned to each symbol by the symbol table
-// you can use key_to_symstr(key) to find the symbol string for an attribute
+// you can use key_to_sym(key) to find the symbol object for an attribute
+// and symch(ist, symbol) to get the C string version of the symbol object
 attr_key_t attr_first_key(isp ist, obj_p obj);
 attr_key_t attr_next_key(isp ist, obj_p obj, attr_key_t key);
 obj_p attr_value_by_key(isp ist, obj_p obj, attr_key_t key);
-char* key_to_symstr(isp ist, attr_key_t key);
+obj_p key_to_sym(isp ist, attr_key_t key);
 
 // INS_PROTO: Insert an object in the list of proto objects.
 // This is the immediate protos for an object, not the reachable.
@@ -1029,10 +1030,12 @@
 
 //********************** CONVENIENT FUNCTION CALLS ****************************
 
-// CALL_FUNCn: Macros to easily call functions with zero or one param
+// CALL_FUNCn: Macros to easily call functions with zero or more params
 obj_p call_func1_f(isp ist, obj_p self, obj_p sym, obj_p parm);
-#define call_func0(ist, self, sym)			call_func((ist), (self), (sym), 0, NULL, NULL)
-#define call_func1(ist, self, sym, parm)	call_func1_f((ist), (self), (sym), (parm))
+obj_p call_func2_f(isp ist, obj_p self, obj_p sym, obj_p parm1, obj_p parm2);
+#define call_func0(ist, self, sym)					call_func((ist), (self), (sym), 0, NULL, NULL)
+#define call_func1(ist, self, sym, parm)			call_func1_f((ist), (self), (sym), (parm))
+#define call_func2(ist, self, sym, parm1, parm2)	call_func2_f((ist), (self), (sym), (parm1), (parm2))
 
 // AS_STR: Call str_ function on any object
 // Get C string representation of any object by calling str_ function on it.

Modified: trunk/include/prothon/prothon_dll.h
===================================================================
--- trunk/include/prothon/prothon_dll.h	2004-05-23 23:51:18 UTC (rev 539)
+++ trunk/include/prothon/prothon_dll.h	2004-05-24 01:48:19 UTC (rev 540)
@@ -101,6 +101,7 @@
 	obj_p		(*call_func)( isp ist, obj_p self, obj_p func_sym, 
 		                      int parm_cnt, obj_p* lbl_val_arr, obj_p dyn_locals );
 	obj_p		(*call_func1_f)(isp ist, obj_p self, obj_p sym, obj_p parm);
+	obj_p		(*call_func2_f)(isp ist, obj_p self, obj_p sym, obj_p parm1, obj_p parm2);
 	obj_p   	(*sym)(isp ist, char* symbol);
 	obj_p		(*new_object)(isp ist, obj_p proto);
 	void		(*copy_object_data)(isp ist, obj_p copy, obj_p obj);
@@ -115,7 +116,8 @@
 	int			(*dict_add)(isp ist, obj_p dict_obj, obj_p key_in, obj_p value_in);
 	obj_p		(*dict_item)(isp ist, obj_p dict_obj, obj_p key_in);
 	int			(*is_unclonable)(obj_p obj);
-	char*		(*key_to_symstr)(isp ist, attr_key_t key);
+	char*		(*symch)(isp ist, obj_p sym_obj);
+	obj_p		(*key_to_sym)(isp ist, attr_key_t key);
 	obj_p		(*new_dict_obj)(isp ist, int initial_size);
 	void		(*dict_clear)(isp ist, obj_p dict_obj);
 	int			(*proto_len)(isp ist, obj_p obj);
@@ -281,6 +283,7 @@
 #define new_C_func_obj		(*services->new_C_func_obj)
 #define call_func			(*services->call_func)
 #define call_func1_f		(*services->call_func1_f)
+#define call_func2_f		(*services->call_func2_f)
 #define new_int_obj			(*services->new_int_obj)
 #define new_float_obj		(*services->new_float_obj)
 #define new_string_obj		(*services->new_string_obj)
@@ -331,8 +334,9 @@
 #define attr_value_by_key	(*services->attr_value_by_key)
 #define dict_add		 	(*services->dict_add)
 #define dict_item		 	(*services->dict_item)		 
-#define is_unclonable	 	(*services->is_unclonable)	 
-#define key_to_symstr	 	(*services->key_to_symstr)	 
+#define is_unclonable	 	(*services->is_unclonable)
+#define symch	 	        (*services->symch)	 
+#define key_to_sym	 	    (*services->key_to_sym)	 
 #define new_dict_obj	 	(*services->new_dict_obj)	 
 #define dict_clear		 	(*services->dict_clear)	 
 #define proto_len		 	(*services->proto_len)		 

Modified: trunk/modules/Prosist/Prosist.c
===================================================================
--- trunk/modules/Prosist/Prosist.c	2004-05-23 23:51:18 UTC (rev 539)
+++ trunk/modules/Prosist/Prosist.c	2004-05-24 01:48:19 UTC (rev 540)
@@ -313,7 +313,7 @@
 	akey = attr_first_key(ist, proxy_obj);
 	if (akey) ADD_CHR('a');
 	while(akey) {
-		ADD_STR(key_to_symstr(ist, akey));
+		ADD_STR(symch(ist, key_to_sym(ist, akey)));
 		ADD_CHR(':');
 		ADD_REF(attr_value_by_key(ist, proxy_obj, akey));
 		ADD_CHR(',');

Added: trunk/src/builtins-attrdict.c
===================================================================
--- trunk/src/builtins-attrdict.c	2004-05-23 23:51:18 UTC (rev 539)
+++ trunk/src/builtins-attrdict.c	2004-05-24 01:48:19 UTC (rev 540)
@@ -0,0 +1,294 @@
+/* ====================================================================
+ * The Prothon License Agreement, Version 1.1
+ *
+ * Copyright (c) 2004 Hahn Creative Applications, http://hahnca.com.
+ * All rights reserved. 
+ *
+ * 1. This LICENSE AGREEMENT is between Hahn Creative Applications ("HCA"),
+ * and the Individual or Organization ("Licensee") accessing and otherwise
+ * using Prothon software in source or binary form and its associated
+ * documentation.
+ * 
+ * 2. Subject to the terms and conditions of this License Agreement, HCA
+ * hereby grants Licensee a nonexclusive, royalty-free, world-wide license
+ * to reproduce, analyze, test, perform and/or display publicly, prepare
+ * derivative works, distribute, and otherwise use Prothon alone or in any
+ * derivative version, provided, however, that HCA's License Agreement and
+ * HCA's notice of copyright, i.e., "Copyright (c) 2004 Hahn Creative
+ * Applications; All Rights Reserved" are retained in Prothon alone or
+ * in any derivative version prepared by Licensee.
+ * 
+ * 3. In the event Licensee prepares a derivative work that is based on or
+ * incorporates Prothon or any part thereof, and wants to make the
+ * derivative work available to others as provided herein, then Licensee
+ * hereby agrees to include in any such work a brief summary of the
+ * changes made to Prothon.
+ * 
+ * 4. HCA is making Prothon available to Licensee on an "AS IS" basis.
+ * HCA MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.  BY WAY
+ * OF EXAMPLE, BUT NOT LIMITATION, HCA MAKES NO AND DISCLAIMS ANY
+ * REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY
+ * PARTICULAR PURPOSE OR THAT THE USE OF PROTHON WILL NOT INFRINGE ANY
+ * THIRD PARTY RIGHTS.
+ * 
+ * 5. HCA SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PROTHON
+ * FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A
+ * RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PROTHON, OR ANY
+ * DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+ * 
+ * 6. This License Agreement will automatically terminate upon a material
+ * breach of its terms and conditions.
+ * 
+ * 7. Nothing in this License Agreement shall be deemed to create any
+ * relationship of agency, partnership, or joint venture between HCA and
+ * Licensee.  This License Agreement does not grant permission to use HCA
+ * trademarks or trade name in a trademark sense to endorse or promote
+ * products or services of Licensee, or any third party.
+ * 
+ * 8. By copying, installing or otherwise using Prothon, Licensee agrees
+ * to be bound by the terms and conditions of this License Agreement.
+ * ====================================================================
+ */
+
+
+// builtins-attrdict.c
+
+#include <stdio.h>
+#include <string.h>
+
+#include <apr_strings.h>
+
+#include <prothon/prothon.h>
+#include "dict.h"
+#include "parser.h"
+#include "object.h"
+#include <prothon/prothon_dll.h>
+
+MODULE_DECLARE(AttrDict);
+
+// ***************************** attr2dict ************************************
+obj_p new_attrdict_obj(isp ist, obj_p obj) {
+	obj_p self = new_object(ist, AttrDict_OBJ);
+	self->data_type = DATA_TYPE_DATAPTR;
+	self->data.ptr  = obj;
+	set_unclonable(self);
+	return self;
+}
+
+// ***************************** attr2dict ************************************
+obj_p attr2dict(isp ist, obj_p self) {
+	int i;
+	size_t alen, asize;
+	attr_p attrp;
+	obj_p dict_obj;
+	rdlock_rtrn(self) NULL;
+	if (!self->has_attrs) {
+		read_unlock(ist, self);
+		return NEW_DICT(0);
+	}
+	attrp = self->attr_proto.attrs;
+	asize = attr_asize(attrp);
+	alen  = attr_alen(attrp);
+	dict_obj = NEW_DICT((int)alen);
+	for (i=0; i < (int) asize; i++) {
+		if (attr_ap(attrp,i)->attr.key > 0)
+			dict_add( ist, dict_obj, key_to_sym(ist, attr_ap(attrp,i)->attr.key),
+			                         attr_ap(attrp,i)->attr.value );
+	}
+	read_unlock(ist, self);
+	return dict_obj;
+}
+
+// ***************************** ATTRDICT *************************************
+
+MODULE_START(AttrDict)
+{
+	AttrDict_OBJ = NEW_OBJ(NULL);
+	MODULE_SET_DOC(AttrDict, "attribute fake dictionary prototype");
+	set_obj_id(AttrDict_OBJ, *, AttrDict);
+	set_attr(ist, OBJ(OBJECT), sym(ist, "AttrDict"), AttrDict_OBJ);
+
+	AttrDict_OBJ->data_type = DATA_TYPE_DATAPTR;
+	AttrDict_OBJ->data.ptr  = OBJ(OBJECT);
+	set_unclonable(AttrDict_OBJ);
+}
+
+DEF(AttrDict, init_, FORM_RPARAM) {
+    BIN_EMPTY_CHK();
+	self->data_type = DATA_TYPE_DATAPTR;
+	self->data.ptr  = parms[1];
+	set_unclonable(self);
+	return OBJ(NONE);
+}
+
+DEF(AttrDict, str_, NULL) {
+	obj_p res, dict;
+	BIN_STR_CHK(AttrDict);
+	res = call_func0(ist, dict = attr2dict(ist, self->data.ptr), SYM(STR_));
+	del_unlock(dict);
+	return res;
+}
+
+DEF(AttrDict, hasKey_QUES, FPARM1(k, NULL)) {
+	obj_p res, dict;
+	BIN_CONTENT_CHK(AttrDict);
+	res = call_func1( ist, dict = attr2dict(ist, self->data.ptr), 
+						   sym(ist, "hasKey_QUES"), parms[1] );
+	del_unlock(dict);
+	return res;
+}
+
+DEF(AttrDict, get, FPARM2(k, NULL, x, OBJ(NONE))) {
+	obj_p res, dict;
+	BIN_CONTENT_CHK(AttrDict);
+	res = call_func2( ist, dict = attr2dict(ist, self->data.ptr), 
+						   sym(ist, "get"), parms[1], parms[3] );
+	del_unlock(dict);
+	return res;
+}
+
+DEF(AttrDict, rIn__QUES, FORM_RPARAM) {
+	obj_p res, dict;
+	BIN_CONTENT_CHK(AttrDict);
+	res = call_func1( ist, dict = attr2dict(ist, self->data.ptr), 
+						   sym(ist, "rIn__QUES"), parms[1] );
+	del_unlock(dict);
+	return res;
+}
+
+DEF(AttrDict, rNotIn__QUES, FORM_RPARAM) {
+	obj_p res, dict;
+	BIN_CONTENT_CHK(AttrDict);
+	res = call_func1( ist, dict = attr2dict(ist, self->data.ptr), 
+						   sym(ist, "rNotIn__QUES"), parms[1] );
+	del_unlock(dict);
+	return res;
+}
+
+DEF(AttrDict, objList_, FORM_RPARAM) {
+	BIN_CONTENT_CHK(AttrDict);
+	return parms[1];
+}
+
+DEF(AttrDict, getItem_, FORM_RPARAM) {
+	obj_p res, index;
+	BIN_CONTENT_CHK(AttrDict);
+	if (list_len(ist, parms[1]) > 1) {
+		raise_exception(ist, OBJ(INTERPRETER_EXC), "slice not allowed in attr dictionary indexing");	
+		return NULL;
+	}
+	index = list_item(ist, parms[1], 0);
+	if (has_proto_QUES(ist, index, OBJ(SYMBOL_PROTO)))
+		res = call_func1(ist, self->data.ptr, SYM(GETITEM_), index);
+	else if (has_proto_QUES(ist, index, OBJ(STRING_PROTO))) {
+		res = call_func1(ist, self->data.ptr, SYM(GETITEM_), sym(ist, pr_strptr(index)));
+	} else
+		raise_exception(ist, OBJ(TYPE_EXC), "attrs_ index must be a string or symbol");
+	return res;
+}
+
+DEF(AttrDict, setItem_, FORM_PARAM2) {
+	obj_p index;
+	BIN_CONTENT_CHK(AttrDict);
+	if (list_len(ist, parms[1]) > 1) {
+		raise_exception(ist, OBJ(INTERPRETER_EXC), "slice not allowed in attr dictionary indexing");	
+		return NULL;
+	}
+	index = list_item(ist, parms[1], 0);
+	if (has_proto_QUES(ist, index, OBJ(SYMBOL_PROTO)))
+		call_func2(ist, self->data.ptr, SYM(SETITEM_), index, parms[3]);
+	else if (has_proto_QUES(ist, index, OBJ(STRING_PROTO))) {
+		call_func2(ist, self->data.ptr, SYM(SETITEM_), sym(ist, pr_strptr(index)), parms[3]);
+	} else
+		raise_exception(ist, OBJ(TYPE_EXC), "attrs_ index must be a string or symbol");
+	return NULL;
+}
+
+DEF(AttrDict, delItem_, FORM_RPARAM) {
+	obj_p index;
+	BIN_CONTENT_CHK(AttrDict);
+	if (list_len(ist, parms[1]) > 1) {
+		raise_exception(ist, OBJ(INTERPRETER_EXC), "slice not allowed in attr dictionary indexing");	
+		return NULL;
+	}
+	index = list_item(ist, parms[1], 0);
+	if (has_proto_QUES(ist, index, OBJ(SYMBOL_PROTO)))
+		call_func1(ist, self->data.ptr, SYM(DELITEM_), index);
+	else if (has_proto_QUES(ist, index, OBJ(STRING_PROTO))) {
+		call_func1(ist, self->data.ptr, SYM(DELITEM_), sym(ist, pr_strptr(index)));
+	} else
+		raise_exception(ist, OBJ(TYPE_EXC), "attrs_ index must be a string or symbol");
+	return NULL;
+}
+
+DEF(AttrDict, len, NULL) {
+	obj_p obj;
+	int res;
+	BIN_CONTENT_CHK(AttrDict);
+	obj = self->data.ptr;
+	if (obj->has_attrs)
+		res = attr_alen(obj->attr_proto.attrs);
+	else
+		res = 0;
+	return NEW_INT(res);
+}
+
+DEF(AttrDict, items, NULL) {
+	obj_p res, dict;
+	BIN_CONTENT_CHK(AttrDict);
+	res = dict_keys_values(ist, dict = attr2dict(ist, self->data.ptr), 3 );
+	del_unlock(dict);
+	return res;
+}
+
+DEF(AttrDict, keys, NULL) {
+	obj_p res, dict;
+	BIN_CONTENT_CHK(AttrDict);
+	res = dict_keys_values(ist, dict = attr2dict(ist, self->data.ptr), 1 );
+	del_unlock(dict);
+	return res;
+}
+
+DEF(AttrDict, values, NULL) {
+	obj_p res, dict;
+	BIN_CONTENT_CHK(AttrDict);
+	res = dict_keys_values(ist, dict = attr2dict(ist, self->data.ptr), 0 );
+	del_unlock(dict);
+	return res;
+}
+
+DEF(AttrDict, clear_BANG, NULL) {
+	obj_p obj;
+	attr_p attrp;
+	BIN_CONTENT_CHK(AttrDict);
+	obj = self->data.ptr;
+	write_lock(ist, obj);
+	attrp = obj->attr_proto.attrs;
+	memset(attr_ap(attrp, 0), 0, attr_asize(attrp) * sizeof(attr_t));
+	attr_alen(attrp) = 0;
+	write_unlock(ist, obj);
+	return self;
+}
+
+MAIN_MODULE_INIT(AttrDict)
+{
+	MODULE_SUB_INIT(AttrDict);
+	MODULE_ADD_SYM(AttrDict, init_);
+	MODULE_ADD_SYM(AttrDict, str_);
+	MODULE_ADD_SYM(AttrDict, hasKey_QUES);
+	MODULE_ADD_SYM(AttrDict, items);
+	MODULE_ADD_SYM(AttrDict, len);
+	MODULE_ADD_SYM(AttrDict, keys);
+	MODULE_ADD_SYM(AttrDict, values);
+	MODULE_ADD_SYM(AttrDict, get);
+	MODULE_ADD_SYM(AttrDict, clear_BANG);
+	MODULE_ADD_SYM(AttrDict, rIn__QUES);
+	MODULE_ADD_SYM(AttrDict, rNotIn__QUES);
+	MODULE_ADD_SYM(AttrDict, getItem_);
+	MODULE_ADD_SYM(AttrDict, setItem_);
+	MODULE_ADD_SYM(AttrDict, delItem_);
+
+	MODULE_ADD_SYM(AttrDict, objList_);
+
+	check_exceptions(ist);
+}
Modified: trunk/src/builtins-core.c
===================================================================
--- trunk/src/builtins-core.c	2004-05-23 23:51:18 UTC (rev 539)
+++ trunk/src/builtins-core.c	2004-05-24 01:48:19 UTC (rev 540)
@@ -353,22 +353,7 @@
 }
 
 DEF(Object, attrs, NULL) { 
-	int i;
-	size_t alen, asize;
-	attr_p attrp;
-	obj_p dict_obj;
-	if (!self->has_attrs) return NEW_DICT(0);
-	attrp = self->attr_proto.attrs;
-	asize = attr_asize(attrp);
-	alen  = attr_alen(attrp);
-	dict_obj = NEW_DICT((int)alen);
-	for (i=0; i < (int) asize; i++) {
-		if (attr_ap(attrp,i)->attr.key > 0)
-			dict_add( ist, dict_obj, 
-					  NEW_STRING(key_to_symstr(ist, attr_ap(attrp,i)->attr.key)),
-			          attr_ap(attrp,i)->attr.value );
-	}
-	return dict_obj;
+	return new_attrdict_obj(ist, self);
 }
 
 DEF(Object, CurrentThread, NULL) {

Modified: trunk/src/builtins-dict.c
===================================================================
--- trunk/src/builtins-dict.c	2004-05-23 23:51:18 UTC (rev 539)
+++ trunk/src/builtins-dict.c	2004-05-24 01:48:19 UTC (rev 540)
@@ -51,7 +51,7 @@
  */
 
 
-// builtins.c
+// builtins-dict.c
 
 #include <stdio.h>
 #include <string.h>

Modified: trunk/src/object.c
===================================================================
--- trunk/src/object.c	2004-05-23 23:51:18 UTC (rev 539)
+++ trunk/src/object.c	2004-05-24 01:48:19 UTC (rev 540)
@@ -130,7 +130,7 @@
 	dll_services.ins_proto		  = ins_proto;		
 	dll_services.del_proto		  = del_proto;		
 	dll_services.has_proto_QUES	  = has_proto_QUES;	
-	dll_services.switch_proto  = switch_proto;
+	dll_services.switch_proto     = switch_proto;
 	dll_services.list_append	  = list_append;
 	dll_services.list_item		  = list_item;	
 	dll_services.list_item_set	  = list_item_set;	
@@ -149,6 +149,7 @@
 	dll_services.new_C_func_obj	  = new_C_func_obj;	
 	dll_services.call_func		  = call_func;
 	dll_services.call_func1_f	  = call_func1_f;
+	dll_services.call_func2_f	  = call_func2_f;
 	dll_services.sym			  = sym;			
 	dll_services.list1			  = list1;		
 	dll_services.list2			  = list2;		
@@ -192,7 +193,8 @@
 	dll_services.dict_add		   = dict_add;
 	dll_services.dict_item		   = dict_item;		  
 	dll_services.is_unclonable	   = is_unclonable;
-	dll_services.key_to_symstr	   = key_to_symstr;	  
+	dll_services.symch   		   = symch;	  
+	dll_services.key_to_sym		   = key_to_sym;	  
 	dll_services.new_dict_obj	   = new_dict_obj;	  
 	dll_services.dict_clear	       = dict_clear;	  
 	dll_services.proto_len		   = proto_len;	  
@@ -239,6 +241,7 @@
 	/* Now load the actual modules for the builtin prototypes */
 	BUILTIN_LOAD(Core);
 	BUILTIN_LOAD(Dict);
+	BUILTIN_LOAD(AttrDict);
 	BUILTIN_LOAD(Float);
 	BUILTIN_LOAD(Int);
 	BUILTIN_LOAD(List);
@@ -1062,7 +1065,7 @@
 	return hash_obj;
 }
 
-//********************************* call_func1 ********************************
+//********************************* call_func1_f ********************************
 obj_p call_func1_f(isp ist, obj_p self, obj_p sym, obj_p parm) {
 	obj_p arr[2];
 	arr[0] = NULL; 
@@ -1070,7 +1073,15 @@
 	return call_func(ist, self, sym, 2, arr, NULL);
 }
 
+//********************************* call_func2_f ********************************
+obj_p call_func2_f(isp ist, obj_p self, obj_p sym, obj_p parm1, obj_p parm2) {
+	obj_p arr[4];
+	arr[0] = NULL;  arr[1] = parm1; 
+	arr[2] = NULL;  arr[3] = parm2; 
+	return call_func(ist, self, sym, 4, arr, NULL);
+}
 
+
 //********************************* set_obj_doc ***********************************
 void set_obj_doc_f(isp ist, obj_p obj, char* str){
 	if (str[strlen(str)-1] == '\n') {
@@ -1109,16 +1120,15 @@
 
 
 
-//********************************* key_to_symstr *************************************
-char* key_to_symstr(isp ist, attr_key_t key) {
-	char* res;
-	obj_p key_obj = NEW_INT(key);
+//********************************* key_to_sym *************************************
+obj_p key_to_sym(isp ist, attr_key_t key) {
+	obj_p res, key_obj = NEW_INT(key);
 	obj_p sym_obj = dict_item(ist, OBJ(SYMBOLS), key_obj);
 	if (!sym_obj) {
-		raise_exception(ist, OBJ(INTERNAL_EXC), "key_to_symstr sym lookup error");
-		res = "";
+		raise_exception(ist, OBJ(INTERNAL_EXC), "key_to_sym lookup error");
+		res = NULL;
 	} else
-		res = symch(ist, sym_obj);
+		res = sym_obj;
 	del_unlock(key_obj);
 	return res;
 }
@@ -1174,9 +1184,9 @@
 				char* sstr;
 				attr_key_t key = attrs[i].attr.key;
 				obj_p val = attrs[i].attr.value;
-				sstr = key_to_symstr(ist, key);
+				sstr = symch(ist, key_to_sym(ist, key));
 				if (catch_exception(ist, OBJ(INTERNAL_EXC), NULL))
-					sstr = "<***err in key_to_symstr>";
+					sstr = "<***err in key_to_sym>";
 				ind(dep+1); fprintf(fout,"KEY: %s\n", sstr); prt_flg = 1;
 				ind(dep+1); fprintf(fout,"VALUE: ");prt_flg = 1;
 				if (val) dump_obj(ist, val, dep+1);

Modified: trunk/src/object.h
===================================================================
--- trunk/src/object.h	2004-05-23 23:51:18 UTC (rev 539)
+++ trunk/src/object.h	2004-05-24 01:48:19 UTC (rev 540)
@@ -138,6 +138,7 @@
 void set_item(isp ist, obj_p ref_self, obj_p ref_key, obj_p value);
 void del_item(isp ist, obj_p ref_self, obj_p ref_key);
 
+obj_p new_attrdict_obj(isp ist, obj_p obj);
 obj_p new_float_obj(isp ist, double num);
 obj_p new_hash_obj(isp ist, i32_t num);
 

Modified: trunk/src/src.vcproj
===================================================================
--- trunk/src/src.vcproj	2004-05-23 23:51:18 UTC (rev 539)
+++ trunk/src/src.vcproj	2004-05-24 01:48:19 UTC (rev 540)
@@ -134,6 +134,9 @@
 				RelativePath=".\argproc.c">
 			</File>
 			<File
+				RelativePath=".\builtins-attrdict.c">
+			</File>
+			<File
 				RelativePath=".\builtins-core.c">
 			</File>
 			<File