fixed bug in prepareStackForAbsOpt (rtemgr.c).
[bugg-scheme-compiler.git] / src / c / scheme.c~
blob475beb51903c7b6a0f490c9bb6124565cdb025d5
1 /* scheme.c
2  * The run-time support needed for the Scheme->C compiler.
3  * Programmer: Mayer Goldberg, 2000
4  */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include "assertions.h" /* check this out: great for debugging */
10 #include "scheme.h"
12 #define STRING_ALLOC(s, n) do { \
13           s = (char *)autoMalloc((n)*sizeof(char)); \
14         } while (0)
16 SchemeObject *makeSchemeObject()
18   SchemeObject *sob;
20   sob = (SchemeObject *)autoMalloc(sizeof(SchemeObject));
21   SOB_DATA(sob) = NULL;
23   return sob;
26 SchemeObject *makeSchemeVoid()
28   SchemeObject *sob;
30   sob = makeSchemeObject();
31   SOB_TYPE(sob) = SCHEME_VOID;
32   SOB_DATA(sob) = NULL;
34   return sob;
37 SchemeObject *makeSchemeInt(int n)
39   SchemeObject *sob;
41   sob = makeSchemeObject();
42   SOB_TYPE(sob) = SCHEME_INT;
43   SOB_DATA(sob) = SOD(autoMalloc(sizeof(SchemeIntData)));
44   SOB_INT_VALUE(sob) = n;
46   return sob;
49 SchemeObject *makeSchemeChar(char c)
51   SchemeObject *sob;
53   sob = makeSchemeObject();
54   SOB_TYPE(sob) = SCHEME_CHAR;
55   SOB_DATA(sob) = SOD(autoMalloc(sizeof(SchemeCharData)));
56   SOB_CHAR_VALUE(sob) = c;
58   return sob;
61 SchemeObject *makeSchemeBool(int b)
63   SchemeObject *sob;
65   sob = makeSchemeObject();
66   SOB_TYPE(sob) = SCHEME_BOOL;
67   SOB_DATA(sob) = SOD(autoMalloc(sizeof(SchemeBoolData)));
69   SOB_BOOL_VALUE(sob) = b;
71   return sob;
74 SchemeObject *makeSchemeString(int n, char c)
76   SchemeObject *sob;
77   int i;
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);
90   }
92   SOB_STRING_SET(sob, n, '\0');
94   return sob;
97 SchemeObject *makeSchemeStringFromCString(char *s)
99   SchemeObject *sob;
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);
110   return sob;
113 SchemeObject *makeSchemeNil()
115   SchemeObject *sob;
117   sob = makeSchemeObject();
118   SOB_TYPE(sob) = SCHEME_NIL;
120   return sob;
123 SchemeObject *makeSchemePair(SchemeObject *car, SchemeObject *cdr)
125   SchemeObject *sob;
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;
134   return sob;
137 SchemeObject *makeSchemeVectorInit(int n, SchemeObject *initSob)
139   SchemeObject *sob;
140   int i;
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);
155   }
157   return sob;
160 extern SymbolNode *topLevel;
162 SchemeObject *makeSchemeSymbol(char *s)
164   int len;
165   SchemeObject *sob;
167   len = strlen(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);
176   return sob;
179 SchemeObject *makeSchemeClosure(void* env,void* code)
181   SchemeObject *sob;
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;
192   return sob;
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)
208   SchemeType sobType;
210   sobType = SOB_TYPE(sob);
211   switch (sobType) {
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);
222   default:
223     ASSERT_ALWAYS((sobType >= SCHEME_TYPE_FIRST) && 
224                   (sobType < SCHEME_TYPE_END));
226     fprintf(stderr,
227             "Non exhaustive switch in file \"%s\", line %d\n",
228                     __FILE__, __LINE__);
229             exit(-1);
230   }
233 #define VOID_PRINT_STRING "#<void object>"
235 char *sobVoidToString(SchemeObject *sob)
237   char *res;
239   STRING_ALLOC(res, 1 + sizeof(VOID_PRINT_STRING));
240   sprintf(res, "%s", VOID_PRINT_STRING);
242   return res;
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));
254   strcpy(res, buf);
256   return res;
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);
267   if (c == ' ') {
268     sprintf(buf, "#\\space");
269   }
270   else if (c == '\n') {
271     sprintf(buf, "#\\newline");
272   }
273   else if (c == '\r') {
274     sprintf(buf, "#\\return");
275   }
276   else if (c == '\f') {
277     sprintf(buf, "#\\page");
278   }
279   else if (c < ' ') {
280     int o1, o2, o3;
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);
286   }
287   else {
288     sprintf(buf, "#\\%c", c);
289   }
291   STRING_ALLOC(res, 1 + strlen(buf));
292   strcpy(res, buf);
294   return res;
297 #define MAX_BOOLEAN_LENGTH 32
299 char *sobBoolToString(SchemeObject *sob)
301   char buf[MAX_BOOLEAN_LENGTH], *res;
302   int b;
304   b = SOB_BOOL_VALUE(sob);
305   switch (b) {
306   case 0: sprintf(buf, "#f"); break;
307   case 1: sprintf(buf, "#t"); break;
308   default:
309     ASSERT_ALWAYS((b != 0) && (b != 1));
310   }
312   STRING_ALLOC(res, 1 + strlen(buf));
313   strcpy(res, buf);
315   return res;
318 char *sobStringToString(SchemeObject *sob)
320   char *src, *dst, *res;
321   int srcLen, i, j;
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) {
328     switch (src[i]) {
329     case '\\':
330       dst[j++] = '\\'; dst[j++] = '\\'; break;
331     case '"':
332       dst[j++] = '\\'; dst[j++] = '"'; break;
333     default:
334       dst[j++] = src[i];
335     }
336   }
338   dst[j] = '\0';
340   STRING_ALLOC(res, 3 + strlen(dst));
341   strcpy(res, "\"");
342   strcat(res, dst);
343   strcat(res, "\"");
345   return res;
348 #define MAX_NIL_LENGTH 32
350 char *sobNilToString(SchemeObject *sob)
352   char buf[MAX_NIL_LENGTH], *res;
354   sprintf(buf, "()");
356   STRING_ALLOC(res, 1 + strlen(buf));
357   strcpy(res, buf);
359   return res;
362 char *sobPairToString(SchemeObject *sob)
364   char *tmp1, *tmp2, *res;
365   SchemeObject *cdr;
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);
372   }
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);
377   }
378   else {
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);
383   }
385   return res;
388 #define MAX_VECTOR_TEMP_LENGTH 32
390 char *sobVectorToString(SchemeObject *sob)
392   char *res, tmp[MAX_VECTOR_TEMP_LENGTH];
393   int len, i;
395   len = SOB_VECTOR_LENGTH(sob);
396   if (len == 0) {
397     STRING_ALLOC(res, 5);
398     strcpy(res, "#0()");
400     return res;
401   }
402   else {
403     char **eltStr;
404     int resSize;
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]);
411     }
413     sprintf(tmp, "#%d(", len);
414     resSize += strlen(tmp);
416     STRING_ALLOC(res, resSize);
417     strcpy(res, tmp);
418     strcat(res, eltStr[0]); autoFree(eltStr[0]);
420     for (i = 1; i < len; ++i) {
421       strcat(res, " ");
422       strcat(res, eltStr[i]); autoFree(eltStr[i]);
423     }
425     autoFree(eltStr);
427     strcat(res, ")");
429     return res;
430   }
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);
442   len = strlen(tmp);
444   for (i = 0, isSpecial = 0; i < len; ++i) {
445     if (strchr(SYMBOL_CHARS, tmp[i]) == NULL) {
446       isSpecial = 1;
447       break;
448     }
449   }
451   if (isSpecial) {
452     STRING_ALLOC(res, 3 + len);
453     sprintf(res, "|%s|", tmp);
454   } 
455   else {
456     STRING_ALLOC(res, 1 + len);
457     sprintf(res, "%s", tmp);
458   }
460   return res;
463 #define CLOSURE_STRING "#<compiled closure>"
465 char *sobClosureToString(SchemeObject *sob)
467   char *res;
469   STRING_ALLOC(res, 1 + sizeof(CLOSURE_STRING));
470   strcpy(res, CLOSURE_STRING);
472   return res;
475 /* support for the top level; this is not a hash table -- see header
476  * file for details.  
477  */
479 SymbolEntry *probeSymbolDefined(char *name, SymbolNode *t)
481   int compare;
483   if (t == NULL) { return NULL; }
485   compare = strcmp(name, SYM_NAME(t));
486   if (compare == 0) {
487     return SYM_ENTRY(t);
488   }
489   else if (compare < 0) {
490     return probeSymbolDefined(name, SYM_LEFT(t));
491   } 
492   else {
493     return probeSymbolDefined(name, SYM_RIGHT(t));
494   }
497 SymbolNode *newSymbolNode(char *name);
499 SymbolEntry *getSymbol(char *name, SymbolNode *t)
501   int compare;
502   SymbolNode *child;
504   if (t == NULL) {
505     if (t == topLevel) {
506       topLevel = newSymbolNode(name);
508       return SYM_ENTRY(topLevel);
509     }
510     else {
511       ASSERT_ALWAYS(t != NULL);
512     }
513   }
515   compare = strcmp(name, SYM_NAME(t));
517   if (compare == 0) {
518     return SYM_ENTRY(t);
519   }
520   else if (compare < 0) {
521     child = SYM_LEFT(t);
522     if (child == NULL) {
523       child = newSymbolNode(name);
524       SYM_LEFT(t) = child;
526       return SYM_ENTRY(child);
527     }
528     else {
529       return getSymbol(name, child);
530     }
531   }
532   else {
533     child = SYM_RIGHT(t);
534     if (child == NULL) {
535       child = newSymbolNode(name);
536       SYM_RIGHT(t) = child;
538       return SYM_ENTRY(child);
539     }
540     else {
541       return getSymbol(name, child);
542     }
543   }
546 SymbolNode *newSymbolNode(char *name)
548   SymbolNode *child;
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;
558   return child;
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. :)
565  */
566 void *autoMalloc(int n)
568   void *tmp;
570   if (n == 0) {
571     return NULL;
572   }
573   else {
574     tmp = (void *)malloc(n);
575     ASSERT_ALWAYS(tmp != NULL);
577     return tmp;
578   }
581 void autoFree(void *p)
583   if (p != NULL) {
584     free(p);
585   }