/* #include */ #include #include #include #include /* simple tagging * ends in 00: pointer * 1: fixnum * 010: symbol * 0110: char * 1110: other immediate object (NULL, TRUE, FALSE) */ enum sexp_tags { SEXP_PAIR, SEXP_SYMBOL, SEXP_STRING, SEXP_VECTOR, }; /* would need a proper header for GC */ typedef struct sexp_struct { char tag; void *data1; void *data2; } *sexp; #define MAKE_IMMEDIATE(n) ((sexp) ((n<<3) + 6)) #define SEXP_NULL MAKE_IMMEDIATE(0) #define SEXP_FALSE MAKE_IMMEDIATE(1) #define SEXP_TRUE MAKE_IMMEDIATE(2) #define SEXP_EOF MAKE_IMMEDIATE(3) #define SEXP_UNDEF MAKE_IMMEDIATE(4) #define SEXP_CLOSE MAKE_IMMEDIATE(5) /* internal use */ #define SEXP_ERROR MAKE_IMMEDIATE(6) #define SEXP_NULLP(x) ((x) == SEXP_NULL) #define SEXP_POINTERP(x) (((int) x & 3) == 0) #define SEXP_INTEGERP(x) (((int) x & 3) == 1) #define SEXP_CHARP(x) (((int) x & 7) == 2) #define SEXP_PAIRP(x) (SEXP_POINTERP(x) && (x)->tag == SEXP_PAIR) #define SEXP_SYMBOLP(x) (SEXP_POINTERP(x) && (x)->tag == SEXP_SYMBOL) #define SEXP_STRINGP(x) (SEXP_POINTERP(x) && (x)->tag == SEXP_STRING) #define SEXP_ALLOC(size) (malloc(size)) #define SEXP_FREE free #define SEXP_NEW() ((sexp) SEXP_ALLOC(sizeof(sexp))) #define make_integer(n) ((sexp) (((int) n<<2) + 1)) #define unbox_integer(n) ((int) n>>2) #define make_character(n) ((sexp) (((int) n<<3) + 2)) #define unbox_character(n) ((int) n>>3) #define vector_length(x) ((int) x->data1) #define vector_data(x) ((sexp*) x->data2) #define string_length(x) ((int) x->data1) #define string_data(x) ((char*) x->data2) sexp cons(sexp head, sexp tail) { sexp pair = SEXP_NEW(); if (! pair) return SEXP_ERROR; pair->tag = SEXP_PAIR; pair->data1 = (void*) head; pair->data2 = (void*) tail; return pair; } sexp car(sexp obj) { return (SEXP_PAIRP(obj)) ? obj->data1 : SEXP_ERROR; } sexp cdr(sexp obj) { return (SEXP_PAIRP(obj)) ? obj->data2 : SEXP_ERROR; } sexp set_car(sexp obj, sexp val) { if (SEXP_PAIRP(obj)) { return obj->data1 = val; } else { return SEXP_ERROR; } } sexp set_cdr(sexp obj, sexp val) { if (SEXP_PAIRP(obj)) { return obj->data2 = val; } else { return SEXP_ERROR; } } sexp nreverse(sexp ls) { sexp a; sexp b; sexp tmp; if (ls == SEXP_NULL) { return ls; } else if (! SEXP_PAIRP(ls)) { return SEXP_ERROR; } else { b = ls; a=cdr(ls); set_cdr(b, SEXP_NULL); for ( ; SEXP_PAIRP(a); ) { tmp = cdr(a); set_cdr(a, b); b = a; a = tmp; } return b; } } sexp list(int count, ...) { sexp res = SEXP_NULL; sexp elt; int i; va_list ap; va_start(ap, count); for (i=0; itag = SEXP_STRING; s->data1 = (void*) len; s->data2 = (void*) mystr; return s; } sexp intern(char *str) { sexp sym = SEXP_NEW(); if (! sym) return SEXP_ERROR; int len = strlen(str); char *mystr = SEXP_ALLOC(len+1); if (! mystr) { SEXP_FREE(sym); return SEXP_ERROR; } strncpy(mystr, str, len+1); sym->tag = SEXP_SYMBOL; sym->data1 = (void*) len; sym->data2 = (void*) mystr; return sym; } sexp make_vector(int len, sexp dflt) { int i; sexp v = SEXP_NEW(); if (v == NULL) return SEXP_ERROR; sexp *x = (void*) SEXP_ALLOC(len*sizeof(sexp)); if (x == NULL) return SEXP_ERROR; for (i=0; itag = SEXP_VECTOR; v->data1 = (void*) len; v->data2 = (void*) x; return v; } sexp list_to_vector(sexp ls) { sexp vec = make_vector(length(ls), SEXP_FALSE); if (vec == SEXP_ERROR) return vec; sexp x; sexp *elts = vector_data(vec); int i; for (i=0, x=ls; SEXP_PAIRP(x); i++, x=cdr(x)) { elts[i] = car(x); } return vec; } sexp vector(int count, ...) { sexp vec = make_vector(count, SEXP_FALSE); if (vec == SEXP_ERROR) return vec; sexp *elts = vector_data(vec); va_list ap; int i; va_start(ap, count); for (i=0; itag) { case SEXP_PAIR: fprintf(out, "("); write_sexp(out, car(obj)); for (x=cdr(obj); SEXP_PAIRP(x); x=cdr(x)) { fprintf(out, " "); write_sexp(out, car(x)); } if (! SEXP_NULLP(x)) { fprintf(out, " . "); write_sexp(out, x); } fprintf(out, ")"); break; case SEXP_VECTOR: len = vector_length(obj); sexp *elts = vector_data(obj); if (len == 0) { fprintf(out, "#()"); } else { fprintf(out, "#("); write_sexp(out, elts[0]); for (i=1; itag == SEXP_STRING) { fprintf(out, "\""); } break; } } else if (SEXP_INTEGERP(obj)) { fprintf(out, "%d", unbox_integer(obj)); } else if (SEXP_CHARP(obj)) { if (33 <= unbox_character(obj) < 127) { fprintf(out, "#\\%c", unbox_character(obj)); } else { fprintf(out, "#\\x%02d", unbox_character(obj)); } } else { switch ((int) obj) { case (int) SEXP_NULL: fprintf(out, "()"); break; case (int) SEXP_TRUE: fprintf(out, "#t"); break; case (int) SEXP_FALSE: fprintf(out, "#f"); break; case (int) SEXP_EOF: fprintf(out, "#"); break; case (int) SEXP_UNDEF: fprintf(out, "#"); break; default: fprintf(out, "#"); } } } void* free_sexp (sexp obj) { int len, i; sexp *elts; if (SEXP_POINTERP(obj)) { switch (obj->tag) { case SEXP_PAIR: free_sexp(car(obj)); free_sexp(cdr(obj)); break; case SEXP_VECTOR: len = vector_length(obj); elts = vector_data(obj); for (i=0; i "); fflush(stdout); while ((obj = read_sexp(stdin)) != SEXP_EOF) { write_sexp(stdout, obj); fprintf(stdout, "\n> "); fflush(stdout); } fprintf(stdout, "\n"); return 0; }