2 * The run-time support needed for the Scheme->C compiler.
3 * Programmer: Mayer Goldberg, 2000
9 #include "assertions.h" /* check this out: great for debugging */
12 #define STRING_ALLOC(s, n) do { \
13 s = (char *)autoMalloc((n)*sizeof(char)); \
16 SchemeObject *makeSchemeObject()
20 sob = (SchemeObject *)autoMalloc(sizeof(SchemeObject));
26 SchemeObject *makeSchemeVoid()
30 sob = makeSchemeObject();
31 SOB_TYPE(sob) = SCHEME_VOID;
37 SchemeObject *makeSchemeInt(int n)
41 sob = makeSchemeObject();
42 SOB_TYPE(sob) = SCHEME_INT;
43 SOB_DATA(sob) = SOD(autoMalloc(sizeof(SchemeIntData)));
44 SOB_INT_VALUE(sob) = n;
49 SchemeObject *makeSchemeChar(char c)
53 sob = makeSchemeObject();
54 SOB_TYPE(sob) = SCHEME_CHAR;
55 SOB_DATA(sob) = SOD(autoMalloc(sizeof(SchemeCharData)));
56 SOB_CHAR_VALUE(sob) = c;
61 SchemeObject *makeSchemeBool(int b)
65 sob = makeSchemeObject();
66 SOB_TYPE(sob) = SCHEME_BOOL;
67 SOB_DATA(sob) = SOD(autoMalloc(sizeof(SchemeBoolData)));
69 SOB_BOOL_VALUE(sob) = b;
74 SchemeObject *makeSchemeString(int n, char c)
79 ASSERT_ALWAYS(n >= 0);
81 sob = makeSchemeObject();
82 SOB_TYPE(sob) = SCHEME_STRING;
83 SOB_DATA(sob) = SOD(autoMalloc(sizeof(SchemeStringData)));
85 SOB_STRING_LENGTH(sob) = n;
86 SOB_STRING_VALUE(sob) = (char *)autoMalloc(n + 1);
88 for (i = 0; i < n; ++i) {
89 SOB_STRING_SET(sob, i, c);
92 SOB_STRING_SET(sob, n, '\0');
97 SchemeObject *makeSchemeStringFromCString(char *s)
101 sob = makeSchemeObject();
102 SOB_TYPE(sob) = SCHEME_STRING;
103 SOB_DATA(sob) = SOD(autoMalloc(sizeof(SchemeStringData)));
105 SOB_STRING_LENGTH(sob) = strlen(s);
106 SOB_STRING_VALUE(sob) = (char *)autoMalloc(1 + SOB_STRING_LENGTH(sob));
108 strcpy(SOB_STRING_VALUE(sob), s);
113 SchemeObject *makeSchemeNil()
117 sob = makeSchemeObject();
118 SOB_TYPE(sob) = SCHEME_NIL;
123 SchemeObject *makeSchemePair(SchemeObject *car, SchemeObject *cdr)
127 sob = makeSchemeObject();
128 SOB_TYPE(sob) = SCHEME_PAIR;
129 SOB_DATA(sob) = SOD(autoMalloc(sizeof(SchemePairData)));
131 SOB_PAIR_CAR(sob) = car;
132 SOB_PAIR_CDR(sob) = cdr;
137 SchemeObject *makeSchemeVectorInit(int n, SchemeObject *initSob)
142 ASSERT_ALWAYS(n >= 0);
144 sob = makeSchemeObject();
145 SOB_TYPE(sob) = SCHEME_VECTOR;
146 SOB_DATA(sob) = (SchemeObjectData *)autoMalloc(sizeof(SchemeVectorData));
148 SOB_VECTOR_LENGTH(sob) = n;
150 SOB_VECTOR_VALUE(sob) =
151 (SchemeObject **)autoMalloc(n * sizeof(SchemeObject *));
153 for (i = 0; i < n; ++i) {
154 SOB_VECTOR_SET(sob, i, initSob);
160 extern SymbolNode *topLevel;
162 SchemeObject *makeSchemeSymbol(char *s)
168 ASSERT_ALWAYS(len > 0);
170 sob = makeSchemeObject();
171 SOB_TYPE(sob) = SCHEME_SYMBOL;
172 SOB_DATA(sob) = SOD(autoMalloc(sizeof(SchemeSymbolData)));
174 SOB_SYMBOL_ENTRY(sob) = getSymbol(s, topLevel);
179 SchemeObject *makeSchemeClosure(void* env,void* code)
183 sob = makeSchemeObject();
184 ASSERT_ALWAYS( sob!=0 );
185 SOB_TYPE(sob) = SCHEME_CLOSURE;
186 SOB_DATA(sob) = SOD(autoMalloc(sizeof(SchemeClosureData)));
187 ASSERT_ALWAYS( SOB_DATA(sob)!=0 );
189 SOB_CLOSURE_ENV(sob) = env;
190 SOB_CLOSURE_CODE(sob) = code;
195 char *sobVoidToString(SchemeObject *sob);
196 char *sobIntToString(SchemeObject *sob);
197 char *sobCharToString(SchemeObject *sob);
198 char *sobBoolToString(SchemeObject *sob);
199 char *sobStringToString(SchemeObject *sob);
200 char *sobNilToString(SchemeObject *sob);
201 char *sobPairToString(SchemeObject *sob);
202 char *sobVectorToString(SchemeObject *sob);
203 char *sobSymbolToString(SchemeObject *sob);
204 char *sobClosureToString(SchemeObject *sob);
206 char *sobToString(SchemeObject *sob)
210 sobType = SOB_TYPE(sob);
212 case SCHEME_VOID: return sobVoidToString(sob);
213 case SCHEME_INT: return sobIntToString(sob);
214 case SCHEME_CHAR: return sobCharToString(sob);
215 case SCHEME_BOOL: return sobBoolToString(sob);
216 case SCHEME_STRING: return sobStringToString(sob);
217 case SCHEME_NIL: return sobNilToString(sob);
218 case SCHEME_PAIR: return sobPairToString(sob);
219 case SCHEME_VECTOR: return sobVectorToString(sob);
220 case SCHEME_SYMBOL: return sobSymbolToString(sob);
221 case SCHEME_CLOSURE: return sobClosureToString(sob);
223 ASSERT_ALWAYS((sobType >= SCHEME_TYPE_FIRST) &&
224 (sobType < SCHEME_TYPE_END));
227 "Non exhaustive switch in file \"%s\", line %d\n",
233 #define VOID_PRINT_STRING "#<void object>"
235 char *sobVoidToString(SchemeObject *sob)
239 STRING_ALLOC(res, 1 + sizeof(VOID_PRINT_STRING));
240 sprintf(res, "%s", VOID_PRINT_STRING);
245 #define MAX_INTEGER_LENGTH 32
247 char *sobIntToString(SchemeObject *sob)
249 char buf[MAX_INTEGER_LENGTH], *res;
251 sprintf(buf, "%d", SOB_INT_VALUE(sob));
253 STRING_ALLOC(res, 1 + strlen(buf));
259 #define MAX_CHAR_LENGTH 32
261 char *sobCharToString(SchemeObject *sob)
263 char c, buf[MAX_CHAR_LENGTH], *res;
265 c = SOB_CHAR_VALUE(sob);
268 sprintf(buf, "#\\space");
270 else if (c == '\n') {
271 sprintf(buf, "#\\newline");
273 else if (c == '\r') {
274 sprintf(buf, "#\\return");
276 else if (c == '\f') {
277 sprintf(buf, "#\\page");
282 o3 = c % 8; c = c >> 3;
283 o2 = c % 8; c = c >> 3;
284 o1 = c % 8; /* not needed; just for good luck :) */
285 sprintf(buf, "#\\%d%d%d", o1, o2, o3);
288 sprintf(buf, "#\\%c", c);
291 STRING_ALLOC(res, 1 + strlen(buf));
297 #define MAX_BOOLEAN_LENGTH 32
299 char *sobBoolToString(SchemeObject *sob)
301 char buf[MAX_BOOLEAN_LENGTH], *res;
304 b = SOB_BOOL_VALUE(sob);
306 case 0: sprintf(buf, "#f"); break;
307 case 1: sprintf(buf, "#t"); break;
309 ASSERT_ALWAYS((b != 0) && (b != 1));
312 STRING_ALLOC(res, 1 + strlen(buf));
318 char *sobStringToString(SchemeObject *sob)
320 char *src, *dst, *res;
323 srcLen = SOB_STRING_LENGTH(sob);
324 src = SOB_STRING_VALUE(sob);
325 dst = (char *)autoMalloc(1 + (srcLen << 1)); /* max possible dst length */
327 for (i = 0, j = 0; i < srcLen; ++i) {
330 dst[j++] = '\\'; dst[j++] = '\\'; break;
332 dst[j++] = '\\'; dst[j++] = '"'; break;
340 STRING_ALLOC(res, 3 + strlen(dst));
348 #define MAX_NIL_LENGTH 32
350 char *sobNilToString(SchemeObject *sob)
352 char buf[MAX_NIL_LENGTH], *res;
356 STRING_ALLOC(res, 1 + strlen(buf));
362 char *sobPairToString(SchemeObject *sob)
364 char *tmp1, *tmp2, *res;
367 tmp1 = sobToString(SOB_PAIR_CAR(sob));
368 cdr = SOB_PAIR_CDR(sob);
369 if (IS_SOB_NIL(cdr)) {
370 STRING_ALLOC(res, 3 + strlen(tmp1));
371 sprintf(res, "(%s)", tmp1); autoFree(tmp1);
373 else if (IS_SOB_PAIR(cdr)) {
374 tmp2 = sobToString(cdr);
375 STRING_ALLOC(res, 3 + strlen(tmp1) + strlen(tmp2));
376 sprintf(res, "(%s %s", tmp1, tmp2 + 1);
379 tmp2 = sobToString(cdr);
380 STRING_ALLOC(res, 6 + strlen(tmp1) + strlen(tmp2));
381 sprintf(res, "(%s . %s)", tmp1, tmp2);
382 autoFree(tmp1); autoFree(tmp2);
388 #define MAX_VECTOR_TEMP_LENGTH 32
390 char *sobVectorToString(SchemeObject *sob)
392 char *res, tmp[MAX_VECTOR_TEMP_LENGTH];
395 len = SOB_VECTOR_LENGTH(sob);
397 STRING_ALLOC(res, 5);
406 eltStr = (char **)autoMalloc(len * sizeof(char *));
408 for (i = 0, resSize = 2 + len; i < len; ++i) {
409 eltStr[i] = sobToString(SOB_VECTOR_REF(sob, i));
410 resSize += strlen(eltStr[i]);
413 sprintf(tmp, "#%d(", len);
414 resSize += strlen(tmp);
416 STRING_ALLOC(res, resSize);
418 strcat(res, eltStr[0]); autoFree(eltStr[0]);
420 for (i = 1; i < len; ++i) {
422 strcat(res, eltStr[i]); autoFree(eltStr[i]);
433 #define SYMBOL_CHARS "abcdefghijklmnopqrstuvwxyz01234567890!@$%^&*_-+=/?:<>,."
435 char *sobSymbolToString(SchemeObject *sob)
437 char *res, *tmp; /*, *buf; */
438 int len, i, isSpecial;
441 tmp = SOB_SYMBOL_NAME(sob);
444 for (i = 0, isSpecial = 0; i < len; ++i) {
445 if (strchr(SYMBOL_CHARS, tmp[i]) == NULL) {
452 STRING_ALLOC(res, 3 + len);
453 sprintf(res, "|%s|", tmp);
456 STRING_ALLOC(res, 1 + len);
457 sprintf(res, "%s", tmp);
463 #define CLOSURE_STRING "#<compiled closure>"
465 char *sobClosureToString(SchemeObject *sob)
469 STRING_ALLOC(res, 1 + sizeof(CLOSURE_STRING));
470 strcpy(res, CLOSURE_STRING);
475 /* support for the top level; this is not a hash table -- see header
479 SymbolEntry *probeSymbolDefined(char *name, SymbolNode *t)
483 if (t == NULL) { return NULL; }
485 compare = strcmp(name, SYM_NAME(t));
489 else if (compare < 0) {
490 return probeSymbolDefined(name, SYM_LEFT(t));
493 return probeSymbolDefined(name, SYM_RIGHT(t));
497 SymbolNode *newSymbolNode(char *name);
499 SymbolEntry *getSymbol(char *name, SymbolNode *t)
506 topLevel = newSymbolNode(name);
508 return SYM_ENTRY(topLevel);
511 ASSERT_ALWAYS(t != NULL);
515 compare = strcmp(name, SYM_NAME(t));
520 else if (compare < 0) {
523 child = newSymbolNode(name);
526 return SYM_ENTRY(child);
529 return getSymbol(name, child);
533 child = SYM_RIGHT(t);
535 child = newSymbolNode(name);
536 SYM_RIGHT(t) = child;
538 return SYM_ENTRY(child);
541 return getSymbol(name, child);
546 SymbolNode *newSymbolNode(char *name)
550 child = (SymbolNode *)autoMalloc(sizeof(SymbolNode));
551 SYM_ENTRY(child) = (SymbolEntry *)autoMalloc(sizeof(SymbolEntry));
552 SYM_NAME(child) = (char *)autoMalloc(1 + strlen(name));
553 strcpy(SYM_NAME(child), name);
554 SYM_HAS_VALUE(child) = 0;
555 SYM_VALUE(child) = NULL;
556 SYM_LEFT(child) = SYM_RIGHT(child) = NULL;
561 /* The procedures autoMalloc and autoFree are interface procedures:
562 * They are meant to be used instead of malloc and free, and are to be
563 * re-defined when the garbage collector is added to the system. Hint:
564 * autoFree will be defined to do nothing. :)
566 void *autoMalloc(int n)
574 tmp = (void *)malloc(n);
575 ASSERT_ALWAYS(tmp != NULL);
581 void autoFree(void *p)