1 /* -*- tab-width:4; -*- */
2 /*
3 * Symbol and Keywords handling
4 *
5 *
6 * Note: code to print and mark symbol is inlined in scm_gc_mark and scm_write
7 *
8 */
9
10 #include "s.h"
11
12 /*-- hashes */
13 SOBJ scm_symbol_hash; /* hash for symbols */
14 SOBJ scm_keyword_hash; /* hash for keywords */
15 int scm_keyword_write_mode; /* write mode for symbols */
16 char *scm_keyword_write_prefix;
17 char *scm_keyword_write_suffix;
18
19 /*-- make a symbol */
20
scm_mksymbol2(SOBJ atom,SOBJ value)21 SOBJ scm_mksymbol2(SOBJ atom, SOBJ value)
22 {
23 SOBJ new = scm_newcell(SOBJ_T_SYMBOL);
24 SCM_SYM_NAME(new) = atom;
25 SCM_SYM_VALUE(new) = value;
26 return(new);
27 }
28
scm_mksymbol(char * str)29 SOBJ scm_mksymbol(char *str)
30 {
31 return(scm_mksymbol2(scm_mkatom(str), scm_unbound));
32 }
33
scm_mkkeyword2(SOBJ atom,SOBJ dummy)34 SOBJ scm_mkkeyword2(SOBJ atom, SOBJ dummy)
35 {
36 SOBJ new = scm_newcell(SOBJ_T_KEYWORD);
37 SCM_KEYW_NAME(new) = atom;
38 return(new);
39 }
40
scm_mkkeyword(char * str)41 SOBJ scm_mkkeyword(char *str)
42 {
43 return(scm_mkkeyword2(scm_mkatom(str), NULL));
44 }
45
scm_symbol_mark(SOBJ obj)46 void scm_symbol_mark(SOBJ obj)
47 {
48 scm_gc_mark(SCM_SYM_NAME(obj));
49 scm_gc_mark(SCM_SYM_VALUE(obj));
50 }
51
scm_symbol_sweep(SOBJ obj)52 void scm_symbol_sweep(SOBJ obj)
53 {
54 }
55
56 /*-- search for a symbol */
scm_symsearch(char * str)57 SOBJ scm_symsearch(char *str)
58 {
59 SOBJ obj = scm_hash_search(scm_symbol_hash, scm_mkatom(str));
60 return( (obj == scm_undefined) ? NULL : obj );
61 }
62
63 /*-- add a new symbol: no duplicate checks are done */
64
scm_atom_hash_complete(SOBJ hash,SOBJ atom,SOBJ (* create)())65 SOBJ scm_atom_hash_complete(SOBJ hash, SOBJ atom, SOBJ (*create)())
66 {
67 int i;
68 SCM_Hash *h;
69 SOBJ p, e;
70
71 h = SCM_HASH(hash);
72 i = scm_hash_code(h, atom);
73 for (p = h->hash[i]; p; p = SCM_CDR(p)) {
74 e = SCM_CAR(p);
75 if (SCM_SYM_NAME(e) == atom) return(e);
76 }
77 e = (*create)(atom, scm_unbound);
78 h->hash[i] = scm_cons(e, h->hash[i]);
79 h->nkeys++;
80
81 if (h->nkeys >= h->maxkeys) { scm_rebuild_hash(hash); }
82 return(e);
83 }
84
scm_symadd(char * str,SOBJ value)85 SOBJ scm_symadd(char *str, SOBJ value)
86 {
87 SOBJ node;
88 SOBJ atom = scm_mkatom(str);
89 node = scm_hash_set(scm_symbol_hash, atom, value);
90 node = scm_hash_search(scm_symbol_hash, atom);
91 #ifdef DEBUG
92 scm_puts("scm_symadd: "); scm_cprint(node);
93 #endif
94 return(node);
95 }
96
scm_sym_clone(SOBJ sym)97 SOBJ scm_sym_clone(SOBJ sym)
98 {
99 return(scm_atom_hash_complete(scm_symbol_hash,
100 SCM_SYM_NAME(sym),
101 scm_mksymbol2));
102 }
103
104 /****************************************************************
105 * Keyword routines
106 ****************************************************************/
scm_keyword_add(char * str)107 SOBJ scm_keyword_add(char *str)
108 {
109 return(scm_atom_hash_complete(scm_keyword_hash,
110 scm_mkatom(str),
111 scm_mkkeyword2));
112 }
113
scm_keywordp(SOBJ obj)114 SOBJ scm_keywordp(SOBJ obj)
115 {
116 return(SCM_MKBOOL(SCM_OBJTYPE(obj) == SOBJ_T_KEYWORD));
117 }
118
scm_keyword_to_string(SOBJ obj)119 SOBJ scm_keyword_to_string(SOBJ obj)
120 {
121 if (!SCM_KEYWORDP(obj)) SCM_ERR("keyword->string: bad keyword", obj);
122 return(scm_atom_to_string(SCM_KEYW_NAME(obj)));
123 }
124
scm_string_to_keyword(SOBJ obj)125 SOBJ scm_string_to_keyword(SOBJ obj)
126 {
127 if (!SCM_STRINGP(obj)) SCM_ERR("string->keyword: bad string", obj);
128 return(scm_keyword_add(SCM_STR_VALUE(obj)));
129 }
130
scm_get_keyword(SOBJ keyw,SOBJ list,SOBJ default_value)131 SOBJ scm_get_keyword(SOBJ keyw, SOBJ list, SOBJ default_value)
132 {
133 if (!SCM_KEYWORDP(keyw)) SCM_ERR("get-keyword: bad keyword", keyw);
134
135 while(list) {
136 if (!SCM_PAIRP(list)) goto bad_list;
137
138 if (!SCM_KEYWORDP(SCM_CAR(list)))
139 SCM_ERR("get-keyword: bad keyword", SCM_CAR(list));
140
141 if (SCM_KEYW_NAME(SCM_CAR(list)) == SCM_KEYW_NAME(keyw)) {
142 list = SCM_CDR(list);
143 if (!SCM_PAIRP(list)) SCM_ERR("get-keyword: bad value", list);
144 return(SCM_CAR(list));
145 }
146 /* jump over value and get next potential keyword */
147 list = SCM_CDR(list); if (!SCM_PAIRP(list)) goto bad_list;
148 list = SCM_CDR(list);
149 }
150 return(default_value);
151
152 bad_list:
153 SCM_ERR("get-keyword: bad list", list);
154 return(NULL);
155 }
156
scm_init_symbol_hash()157 void scm_init_symbol_hash()
158 {
159 scm_symbol_hash = scm_mkhash(SCM_HASH_T_SYMBOL);
160 scm_gc_protect(&scm_symbol_hash);
161
162 scm_keyword_hash= scm_mkhash(SCM_HASH_T_SYMBOL);
163 scm_gc_protect(&scm_keyword_hash);
164 }
165
166 /*E* (keyword-display-type NUMBER) => NUMBER */
167 /*D* Changes the way of keyword display. When NUMBER is 0, the
168 keywords are displayed prefixed by ':', when NUMBER is 1 they are
169 prefixed with '#!' and when NUMBER is 2 they are suffixed with ':' */
scm_keyword_display_type(SOBJ x)170 SOBJ scm_keyword_display_type(SOBJ x)
171 {
172 int mode = SCM_INUM(x);
173 switch(mode) {
174 case SCM_KEYW_WRITE_DEFLT:
175 scm_keyword_write_prefix = ":";
176 scm_keyword_write_suffix = "";
177 break;
178 case SCM_KEYW_WRITE_DSSL:
179 scm_keyword_write_prefix = "#!";
180 scm_keyword_write_suffix = "";
181 break;
182 case SCM_KEYW_WRITE_OTHER:
183 scm_keyword_write_prefix = "";
184 scm_keyword_write_suffix = ":";
185 break;
186 default:
187 mode = SCM_KEYW_WRITE_DEFLT;
188 }
189 scm_keyword_write_mode = mode;
190 return(x);
191 }
192
193 /*E* (gensym [PREFIX]) => SYMBOL */
194 /*D* Returns a new symbol which is guaranted to be unique (during this
195 scheme session). */
scm_gensym(int nargs,SOBJ * arg)196 SOBJ scm_gensym(int nargs, SOBJ *arg)
197 {
198 char *prefix;
199 char buf[128];
200 static int count;
201 SOBJ new;
202
203 if (nargs != 0) {
204 scm_puts("WARNING: gensym ignores prefix argument");
205 }
206 prefix = SCM_GENSYM_PREFIX;
207 sprintf(buf, "%s%d", prefix, count++);
208 new = scm_newcell(SOBJ_T_ATOM);
209 SCM_ATOM_NAME(new) = scm_must_strdup(buf);
210 SCM_ATOM_NEXT(new) = NULL;
211 return(scm_mksymbol2(new, scm_unbound));
212 }
213
214 /*E* (make-symbol NAME) => SYMBOL */
215 /*D* Create an unbound symbol. */
scm_make_symbol(SOBJ name)216 SOBJ scm_make_symbol(SOBJ name)
217 {
218 if (!SCM_ATOMP(name)) SCM_ERR("bad symbol", name);
219 return(scm_mksymbol2(name, scm_unbound));
220 }
221
222 /*E* (symbol-name SYM) => NAME */
223 /*D* Returns the name associated to symbol SYM. NAME is an atom.*/
scm_symbol_name(SOBJ x)224 SOBJ scm_symbol_name(SOBJ x)
225 {
226 if (!SCM_SYMBOLP(x)) SCM_ERR("bad symbol", x);
227 return(SCM_SYM_NAME(x));
228 }
229
230 /*E* (symbol-value SYM) => VALUE */
231 /*D* Returns the value associated to symbol SYM. VALUE is any scheme
232 object. */
scm_symbol_value(SOBJ x)233 SOBJ scm_symbol_value(SOBJ x)
234 {
235 if (!SCM_SYMBOLP(x)) SCM_ERR("bad symbol", x);
236 return(SCM_SYM_VALUE(x));
237 }
238
scm_init_symbol()239 void scm_init_symbol()
240 {
241 scm_keyword_write_mode = SCM_KEYW_WRITE_DEFLT;
242 scm_keyword_write_prefix = ":";
243 scm_keyword_write_suffix = "";
244
245 scm_add_cprim("keyword-display-type", scm_keyword_display_type, 1);
246 scm_add_cprim("gensym", scm_gensym, -1);
247 scm_add_cprim("make-symbol", scm_make_symbol, 1);
248 scm_add_cprim("symbol-name", scm_symbol_name, 1);
249 scm_add_cprim("symbol-value", scm_symbol_value, 1);
250 }
251