1 #ifndef _KLISP_CORE_MODULE_BODY_
2 #define _KLISP_CORE_MODULE_BODY_
7 #ifdef KLISP_DEBUG_EVAL
8 int klispOptPrintStack
= 1;
12 /*****************************************************************
14 *****************************************************************/
15 void KLispFreeError (KLISP_POOL_DEF0
) {
16 if (!KLISP_POOL
|| KLISP_POOL
->errorStatic
|| !KLISP_POOL
->error
) return;
17 KLISP_MEMFREE(KLISP_POOL
->error
);
18 KLISP_POOL
->error
= NULL
;
22 int KLispError (KLISP_POOL_DEF
const char *fmt
, ...) {
23 static char *sErrorMem
= "fatal out of memory!";
28 if (!KLISP_POOL
) return -1;
29 KLispFreeError(KLISP_POOL_ARG0
);
30 if (!fmt
|| !*fmt
) return -1;
32 KLISP_POOL
->errorStatic
= 1; KLISP_POOL
->error
= sErrorMem
;
33 if ((p
= KLISP_MEMALLOC(size
*sizeof(char))) == NULL
) return -1;
37 n
= vsnprintf(p
, size
, fmt
?fmt
:"", ap
);
39 if (n
> -1 && n
< size
) break;
40 if (n
> -1) size
= n
+1; else size
*= 2;
41 if ((np
= KLISP_MEMREALLOC(p
, size
*sizeof(char))) == NULL
) { KLISP_MEMFREE(p
); return -1; }
44 KLISP_POOL
->errorStatic
= 0; KLISP_POOL
->error
= p
;
45 KLISP_POOL
->errorLine
= KLISP_POOL
->lineNo
;
51 int KLispErrorMem (KLISP_POOL_DEF0
) {
52 return KLispError(KLISP_POOL_ARG
"out of memory");
56 /*****************************************************************
57 initializers/allocators
58 *****************************************************************/
59 void KLispFreePool (KLISP_POOL_DEF0
) {
63 if (!KLISP_POOL
) return;
64 KLISP_POOL
->gcPhase
++;
65 for (f
= 0; f
< KLISP_POOL
->cellCount
; f
++) {
66 cell
= &(KLISP_POOL
->cells
[f
]);
67 if (cell
->ctype
& KLISP_FFLAG
) continue;
68 if (cell
->ctype
== KLISP_TYPE_UDATA
&& cell
->finalizer
) KLispInvokeFinalizer(KLISP_POOL_ARG f
);
70 KLISP_POOL
->gcPhase
--;
71 KLispDeinitStack(&KLISP_POOL
->roots
);
72 KLispDeinitStack(&KLISP_POOL
->stack
);
73 KLispDeinitStack(&KLISP_POOL
->frames
);
74 KLispRBTFreeTree(KLISP_POOL
->primitives
);
75 KLispRBTFreeTree(KLISP_POOL
->globals
);
76 KLispRBTFreeTree(KLISP_POOL
->strpool
);
77 KLISP_MEMFREE(KLISP_POOL
->cells
);
78 KLispFreeError(KLISP_POOL_ARG0
);
79 KLISP_MEMFREE(KLISP_POOL
);
83 static void InitPool (KLISP_POOL_DEF
int from
) {
87 if (KLISP_POOL
->free
) KLISP_CELL(KLISP_POOL
->free
).cdr
= from
;
88 KLISP_POOL
->free
= from
;
89 cell
= &(KLISP_CELL(from
));
90 for (f
= from
; f
< KLISP_POOL
->cellCount
; f
++, cell
++) {
91 cell
->ctype
= KLISP_TYPE_NUM
| KLISP_FFLAG
;
94 cell
->car
= cell
->lineno
= 0;
97 KLISP_CELL(KLISP_POOL
->cellCount
-1).cdr
= 0; /* end of free list */
101 TKLispPool
*KLispNewPool (void) {
109 KLISP_POOL
= KLISP_MEMALLOC(sizeof(TKLispPool
));
110 if (!KLISP_POOL
) goto errexit
;
111 memset(KLISP_POOL
, 0, sizeof(TKLispPool
));
113 initPS
= KLISP_INIT_POOL_SIZE
;
114 if (initPS
< KLISP_SPEC_MAX
+16) initPS
= KLISP_INIT_POOL_SIZE
+16;
115 KLISP_POOL
->cellCount
= initPS
;
116 KLISP_POOL
->cells
= KLISP_MEMALLOC(KLISP_POOL
->cellCount
*sizeof(TKLispCell
));
117 if (!KLISP_POOL
->cells
) goto errexit
;
118 memset(KLISP_POOL
->cells
, 0, KLISP_POOL
->cellCount
*sizeof(TKLispCell
));
120 KLISP_POOL
->primitives
= KLispRBTNewTree();
121 if (!KLISP_POOL
->primitives
) goto errexit
;
123 KLISP_POOL
->globals
= KLispRBTNewTree();
124 if (!KLISP_POOL
->globals
) goto errexit
;
125 /* alloc stringling */
126 KLISP_POOL
->strpool
= KLispRBTNewTree();
127 if (!KLISP_POOL
->strpool
) goto errexit
;
129 if (!KLispInitStack(&KLISP_POOL
->frames
, 128, 64, 4096) ||
130 !KLispInitStack(&KLISP_POOL
->stack
, 128, 64, 4096) ||
131 !KLispInitStack(&KLISP_POOL
->roots
, 16, 8, 4096)) goto errexit
;
133 buf
[0] = buf
[1] = buf
[2] = '.'; buf
[3] = '\0';
134 if (!KLispRBTInsert(KLISP_POOL
->strpool
, buf
, 0, 1, NULL
)) goto errexit
;
136 /* fill strpool with chars */
137 for (f
= 1; f
< 256; f
++) {
139 if (!KLispRBTInsert(KLISP_POOL
->strpool
, buf
, 0, 1, NULL
)) goto errexit
;
142 KLISP_POOL
->usedCount
= 0;
144 cell
= KLISP_POOL
->cells
;
145 for (f
= 0; f
< 2; f
++, cell
++) {
146 KLISP_POOL
->usedCount
++;
148 cell
->ctype
= KLISP_TYPE_NUM
;
154 for (f
= 0; f
< 256; f
++, cell
++) {
155 if (f
) { buf
[0] = f
; buf
[1] = '\0'; } else { buf
[0] = buf
[1] = buf
[2] = '.'; buf
[3] = '\0'; }
156 KLISP_POOL
->syms
[f
] = KLISP_POOL
->usedCount
;
157 KLISP_POOL
->usedCount
++;
159 cell
->ctype
= KLISP_TYPE_SYM
;
161 ci
= KLispRBTFind(KLISP_POOL
->strpool
, buf
);
163 ci
->value0
= KLISP_POOL
->syms
[f
];
165 cell
->cdr
= cell
->lineno
= 0;
168 InitPool(KLISP_POOL_ARG KLISP_POOL
->usedCount
);
170 KLISP_POOL
->prog
= KLispNewXPrim(KLISP_POOL_ARG KLISP_TYPE_MPRIM
, NULL
, "prog");
171 KLISP_POOL
->cond
= KLispNewXPrim(KLISP_POOL_ARG KLISP_TYPE_MPRIM
, NULL
, "cond");
172 KLISP_POOL
->lambda
= KLispNewXPrim(KLISP_POOL_ARG KLISP_TYPE_MPRIM
, NULL
, "lambda");
173 KLISP_POOL
->mlambda
= KLispNewXPrim(KLISP_POOL_ARG KLISP_TYPE_MPRIM
, NULL
, "mlambda");
174 KLISP_POOL
->quote
= KLispNewXPrim(KLISP_POOL_ARG KLISP_TYPE_MPRIM
, NULL
, "quote");
175 KLISP_POOL
->defun
= KLispNewXPrim(KLISP_POOL_ARG KLISP_TYPE_MPRIM
, NULL
, "defun");
176 KLISP_POOL
->defmac
= KLispNewXPrim(KLISP_POOL_ARG KLISP_TYPE_MPRIM
, NULL
, "defmac");
177 KLISP_POOL
->invoke
= KLispNewXPrim(KLISP_POOL_ARG KLISP_TYPE_PRIM
, NULL
, "invoke");
179 KLispSetGlobal(KLISP_POOL_ARG
"prog", KLISP_POOL
->prog
);
180 KLispSetGlobal(KLISP_POOL_ARG
"cond", KLISP_POOL
->cond
);
181 KLispSetGlobal(KLISP_POOL_ARG
"lambda", KLISP_POOL
->lambda
);
182 KLispSetGlobal(KLISP_POOL_ARG
"mlambda", KLISP_POOL
->mlambda
);
183 KLispSetGlobal(KLISP_POOL_ARG
"quote", KLISP_POOL
->quote
);
184 KLispSetGlobal(KLISP_POOL_ARG
"defun", KLISP_POOL
->defun
);
185 KLispSetGlobal(KLISP_POOL_ARG
"defmac", KLISP_POOL
->defmac
);
186 KLispSetGlobal(KLISP_POOL_ARG
"invoke", KLISP_POOL
->invoke
);
191 if (KLISP_POOL
->cells
) KLISP_MEMFREE(KLISP_POOL
->cells
);
192 KLispDeinitStack(&KLISP_POOL
->roots
);
193 KLispDeinitStack(&KLISP_POOL
->stack
);
194 KLispDeinitStack(&KLISP_POOL
->frames
);
195 KLispRBTFreeTree(KLISP_POOL
->primitives
);
196 KLispRBTFreeTree(KLISP_POOL
->globals
);
197 KLispRBTFreeTree(KLISP_POOL
->strpool
);
198 KLISP_MEMFREE(KLISP_POOL
);
203 static int AllocCell (KLISP_POOL_DEF0
) {
207 #ifdef KLISP_DEBUG_VERY_AGRESSIVE_GC
208 KLispGC(KLISP_POOL_ARG0
);
210 if (!KLISP_POOL
->free
|| KLISP_POOL
->cellCount
-KLISP_POOL
->usedCount
< KLISP_GROW_POOL_SIZE
/4) {
212 KLispGC(KLISP_POOL_ARG0
);
213 if (!KLISP_POOL
->free
) {
215 newSz
= KLISP_POOL
->cellCount
+KLISP_GROW_POOL_SIZE
;
216 newcp
= KLISP_MEMREALLOC(KLISP_POOL
->cells
, sizeof(TKLispCell
)*newSz
);
217 if (!newcp
) return KLispErrorMem(KLISP_POOL_ARG0
);
218 KLISP_POOL
->cells
= newcp
;
219 f
= KLISP_POOL
->cellCount
;
220 KLISP_POOL
->cellCount
= newSz
;
221 InitPool(KLISP_POOL_ARG f
);
225 if (!KLISP_POOL
->free
) return KLispErrorMem(KLISP_POOL_ARG0
);
226 f
= KLISP_POOL
->free
;
227 newcp
= &(KLISP_POOL
->cells
[f
]);
228 KLISP_POOL
->free
= newcp
->cdr
;
229 newcp
->ctype
= KLISP_TYPE_NUM
;
230 newcp
->car
= newcp
->cdr
= 0;
231 newcp
->lineno
= KLISP_POOL
->lineNo
;
232 KLISP_POOL
->usedCount
++;
238 int KLispNewCons (KLISP_POOL_DEF
int car
, int cdr
) {
241 if (car
< 0 || cdr
< 0) return -1;
242 assert(!KLISP_POOL
->tempRootGC0
&& !KLISP_POOL
->tempRootGC1
);
243 KLISP_POOL
->tempRootGC0
= car
;
244 KLISP_POOL
->tempRootGC1
= cdr
;
245 cell
= AllocCell(KLISP_POOL_ARG0
);
246 KLISP_POOL
->tempRootGC0
= KLISP_POOL
->tempRootGC1
= 0;
248 KLISP_CTYPE(cell
) = KLISP_TYPE_CONS
;
249 KLISP_CAR(cell
) = car
;
250 KLISP_CDR(cell
) = cdr
;
257 int KLispNewNum (KLISP_POOL_DEF TKLispNumber value
) {
260 if ((cell
= AllocCell(KLISP_POOL_ARG0
)) < 0) return -1;
261 KLISP_CTYPE(cell
) = KLISP_TYPE_NUM
;
262 KLISP_CELL(cell
).num
= value
;
268 int KLispNewSym (KLISP_POOL_DEF
const char *value
) {
274 if (*value
&& !value
[1]) return KLISP_POOL
->syms
[*((unsigned char *)value
)];
276 sp
= KLispRBTFind(KLISP_POOL
->strpool
, value
);
277 if (sp
&& sp
->value0
) return sp
->value0
;
279 if ((cell
= AllocCell(KLISP_POOL_ARG0
)) < 0) return -1;
281 if (!(sp
= KLispRBTInsert(KLISP_POOL
->strpool
, value
, cell
, 1, NULL
))) return -1;
282 } else sp
->value0
= cell
;
284 KLISP_CTYPE(cell
) = KLISP_TYPE_SYM
;
285 KLISP_CELL(cell
).str
= sp
->str
;
291 int KLispNewXPrim (KLISP_POOL_DEF
int prtype
, TKLispPrimFn fn
, const char *name
) {
295 assert(name
&& *name
);
297 case KLISP_TYPE_PRIM
: case KLISP_TYPE_MPRIM
:
298 case KLISP_TYPE_IPRIM
: case KLISP_TYPE_IMPRIM
:
300 default: return KLispError(KLISP_POOL_ARG
"KLispNewXPrim: invalid prim type");
303 sp
= KLispRBTFind(KLISP_POOL
->primitives
, name
);
305 if ((cell
= AllocCell(KLISP_POOL_ARG0
)) < 0) return -1;
306 if (!(sp
= KLispRBTInsert(KLISP_POOL
->primitives
, name
, cell
, 1, NULL
))) return -1;
307 KLISP_CELL(cell
).str
= sp
->str
;
308 } else cell
= sp
->value0
;
310 KLISP_CTYPE(cell
) = prtype
;
311 KLISP_CELL(cell
).fn
= fn
;
317 int KLispNewSymbolPair (KLISP_POOL_DEF
const char *name
, int valueCell
) {
321 sym
= KLispNewSym(KLISP_POOL_ARG name
);
322 if (sym
> 0) sym
= KLispNewCons(KLISP_POOL_ARG sym
, valueCell
);
330 car: ptr to cell with some data or nil; cdr: list of methods;
331 list of methods: car: symbol (name . xPRIM); cdr: next
332 method args: (udata_obj ...)
333 call: (udata method ...)
335 int KLispNewUData (KLISP_POOL_DEF
void *ptr
, TKLispFinalizeFn finalizer
) {
338 if ((cell
= KLispNewCons(KLISP_POOL_ARG
0, 0)) < 0) return -1;
339 KLISP_CTYPE(cell
) = KLISP_TYPE_UDATA
;
340 KLISP_CELL(cell
).finalizer
= finalizer
;
341 KLISP_CELL(cell
).udata
= ptr
;
347 /* return 0 or method cell */
348 static int KLispUDataFindMethod (KLISP_POOL_DEF
int udata
, const char *name
) {
351 if (udata
< 2 || KLISP_CTYPE(udata
) != KLISP_TYPE_UDATA
) return -1;
352 mcell
= KLispFindSymbol(KLISP_POOL_ARG
KLISP_CDR(udata
), name
);
354 return mcell
<=0?0:mcell
;
358 int KLispUDataGetMethod (KLISP_POOL_DEF
int udata
, const char *name
) {
361 if ((sym
= KLispUDataFindMethod(KLISP_POOL_ARG udata
, name
)) <= 0) return -1;
363 return KLISP_CDR(sym
);
367 int KLispUDataSetMethod (KLISP_POOL_DEF
int udata
, int methodcell
, const char *name
) {
370 if (methodcell
< 0) return -1;
371 sym
= KLispUDataFindMethod(KLISP_POOL_ARG udata
, name
);
372 if (sym
< 0) return -1;
374 /* create new symbol */
375 if ((sym
= KLispNewSymbolPair(KLISP_POOL_ARG name
, methodcell
)) < 0) return -1;
376 /* add it to method list */
378 t
= KLispNewCons(KLISP_POOL_ARG sym
, KLISP_CDR(udata
));
380 if (t
< 0) return -1;
381 KLISP_CDR(udata
) = t
;
382 } else KLISP_CDR(sym
) = methodcell
;
388 void *KLispUDataGetPtr (KLISP_POOL_DEF
int udata
) {
389 if (udata
< 2 || KLISP_CTYPE(udata
) != KLISP_TYPE_UDATA
) return NULL
;
391 return KLISP_CELL(udata
).udata
;
395 int KLispUDataSetPtr (KLISP_POOL_DEF
int udata
, void *ptr
) {
396 if (udata
< 2 || KLISP_CTYPE(udata
) != KLISP_TYPE_UDATA
) return 0;
398 KLISP_CELL(udata
).udata
= ptr
;
404 int KLispRegisterMethods (KLISP_POOL_DEF
int udatacell
, struct _TKLispPrimItem
*list
) {
405 int methodcell
, res
= 0;
408 /*if (!KLispPushRoot(KLISP_POOL_ARG udatacell)) return -1;*/
409 while (list
&& list
->name
) {
410 methodcell
= KLispNewXPrim(KLISP_POOL_ARG KLISP_TYPE_MPRIM
, list
->fn
, list
->name
);
411 if (methodcell
< 0) goto done
;
412 if (KLispUDataSetMethod(KLISP_POOL_ARG udatacell
, methodcell
, list
->name
) < 0) goto done
;
418 /*KLispPopRoots(KLISP_POOL_ARG 1);*/
424 #endif /* _KLISP_CORE_MODULE_BODY_ */