/* * Bootstrap Scheme - a quick and very dirty Scheme interpreter. * Copyright (C) 2010 Peter Michaux (http://peter.michaux.ca/) * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public * License version 3 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License version 3 for more details. * * You should have received a copy of the GNU Affero General Public * License version 3 along with this program. If not, see * . */ #include #include #include #include /**************************** MODEL ******************************/ typedef enum {FIXNUM} object_type; typedef struct object { object_type type; union { struct { long value; } fixnum; } data; } object; /* no GC so truely "unlimited extent" */ object *alloc_object(void) { object *obj; obj = malloc(sizeof(object)); if (obj == NULL) { fprintf(stderr, "out of memory\n"); exit(1); } return obj; } object *make_fixnum(long value) { object *obj; obj = alloc_object(); obj->type = FIXNUM; obj->data.fixnum.value = value; return obj; } char is_fixnum(object *obj) { return obj->type == FIXNUM; } /***************************** READ ******************************/ char is_delimiter(int c) { return isspace(c) || c == EOF || c == '(' || c == ')' || c == '"' || c == ';'; } int peek(FILE *in) { int c; c = getc(in); ungetc(c, in); return c; } void eat_whitespace(FILE *in) { int c; while ((c = getc(in)) != EOF) { if (isspace(c)) { continue; } else if (c == ';') { /* comments are whitespace also */ printf("c is %c", c); c = getc(in); while ((c != EOF) && (c != '\n')); { c = getc(in); printf("%i", c == '\n'); continue; } } ungetc(c, in); break; } } object *read(FILE *in) { int c; short sign = 1; long num = 0; eat_whitespace(in); c = getc(in); if (isdigit(c) || (c == '-' && (isdigit(peek(in))))) { /* read a fixnum */ if (c == '-') { sign = -1; } else { ungetc(c, in); } while (isdigit(c = getc(in))) { num = (num * 10) + (c - '0'); } num *= sign; if (is_delimiter(c)) { ungetc(c, in); return make_fixnum(num); } else { fprintf(stderr, "number not followed by delimiter\n"); exit(1); } } else { fprintf(stderr, "bad input. Unexpected '%c'\n", c); exit(1); } fprintf(stderr, "read illegal state\n"); exit(1); } /*************************** EVALUATE ****************************/ /* until we have lists and symbols just echo */ object *eval(object *exp) { return exp; } /**************************** PRINT ******************************/ void write(object *obj) { switch (obj->type) { case FIXNUM: printf("%ld", obj->data.fixnum.value); break; default: fprintf(stderr, "cannot write unknown type\n"); exit(1); } } /***************************** REPL ******************************/ int main(void) { printf("Welcome to Bootstrap Scheme. " "Use ctrl-c to exit.\n"); while (1) { printf("> "); write(eval(read(stdin))); printf("\n"); } return 0; } /**************************** MUSIC ******************************* Slipknot, Neil Young, Pearl Jam, The Dead Weather, Dave Matthews Band, Alice in Chains, White Zombie, Blind Melon, Priestess, Puscifer */