1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36: #define LIBGAUCHE_BODY
37: #include "gauche.h"
38:
39:
40:
41:
42:
43: static void keyword_print(ScmObj obj, ScmPort *port, ScmWriteContext *ctx)
44: {
45: if (SCM_WRITE_MODE(ctx) != SCM_WRITE_DISPLAY) {
46: SCM_PUTC(':', port);
47: }
48: SCM_PUTS(SCM_KEYWORD(obj)->name, port);
49: return;
50: }
51:
52: SCM_DEFINE_BUILTIN_CLASS_SIMPLE(Scm_KeywordClass, keyword_print);
53:
54:
55: static struct {
56: ScmHashTable *table;
57: ScmInternalMutex mutex;
58: } keywords = { NULL };
59:
60:
61:
62:
63: ScmObj Scm_MakeKeyword(ScmString *name)
64: {
65: ScmHashEntry *e;
66: ScmObj r;
67:
68: (void)SCM_INTERNAL_MUTEX_LOCK(keywords.mutex);
69: e = Scm_HashTableGet(keywords.table, SCM_OBJ(name));
70: if (e) r = e->value;
71: else {
72: ScmKeyword *k = SCM_NEW(ScmKeyword);
73: SCM_SET_CLASS(k, SCM_CLASS_KEYWORD);
74: k->name = SCM_STRING(Scm_CopyString(name));
75: Scm_HashTablePut(keywords.table, SCM_OBJ(name), SCM_OBJ(k));
76: r = SCM_OBJ(k);
77: }
78: (void)SCM_INTERNAL_MUTEX_UNLOCK(keywords.mutex);
79: return r;
80: }
81:
82: ScmObj Scm_GetKeyword(ScmObj key, ScmObj list, ScmObj fallback)
83: {
84: ScmObj cp;
85: SCM_FOR_EACH(cp, list) {
86: if (!SCM_PAIRP(SCM_CDR(cp))) {
87: Scm_Error("incomplete key list: %S", list);
88: }
89: if (key == SCM_CAR(cp)) return SCM_CADR(cp);
90: cp = SCM_CDR(cp);
91: }
92: if (SCM_UNBOUNDP(fallback)) {
93: Scm_Error("value for key %S is not provided: %S", key, list);
94: }
95: return fallback;
96: }
97:
98: ScmObj Scm_DeleteKeyword(ScmObj key, ScmObj list)
99: {
100: ScmObj cp;
101: SCM_FOR_EACH(cp, list) {
102: if (!SCM_PAIRP(SCM_CDR(cp))) {
103: Scm_Error("incomplete key list: %S", list);
104: }
105: if (key == SCM_CAR(cp)) {
106:
107: ScmObj h = SCM_NIL, t = SCM_NIL;
108: ScmObj tail = Scm_DeleteKeyword(key, SCM_CDR(SCM_CDR(cp)));
109: ScmObj cp2;
110: SCM_FOR_EACH(cp2, list) {
111: if (cp2 == cp) {
112: SCM_APPEND(h, t, tail);
113: return h;
114: } else {
115: SCM_APPEND1(h, t, SCM_CAR(cp2));
116: }
117: }
118: }
119: cp = SCM_CDR(cp);
120: }
121: return list;
122: }
123:
124: ScmObj Scm_DeleteKeywordX(ScmObj key, ScmObj list)
125: {
126: ScmObj cp, prev = SCM_FALSE;
127: SCM_FOR_EACH(cp, list) {
128: if (!SCM_PAIRP(SCM_CDR(cp))) {
129: Scm_Error("incomplete key list: %S", list);
130: }
131: if (key == SCM_CAR(cp)) {
132:
133: if (SCM_FALSEP(prev)) {
134:
135: return Scm_DeleteKeywordX(key, SCM_CDR(SCM_CDR(cp)));
136: } else {
137: ScmObj tail = Scm_DeleteKeywordX(key, SCM_CDR(SCM_CDR(cp)));
138: SCM_SET_CDR(prev, tail);
139: return list;
140: }
141: }
142: cp = SCM_CDR(cp);
143: prev = cp;
144: }
145: return list;
146: }
147:
148: void Scm__InitKeyword(void)
149: {
150: (void)SCM_INTERNAL_MUTEX_INIT(keywords.mutex);
151: keywords.table = SCM_HASH_TABLE(Scm_MakeHashTableSimple(SCM_HASH_STRING, 256));
152: }