asdf

Dependencies:   mbed

Fork of manworm_ticker_tv by Bayley Wang

Committer:
dicarloj
Date:
Fri May 04 01:45:05 2018 +0000
Revision:
12:e99cc1e9d928
Parent:
10:1163fb31b0a7
lol it works;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dicarloj 10:1163fb31b0a7 1 /* A minimal Lisp interpreter
dicarloj 10:1163fb31b0a7 2 Copyright 2004 Andru Luvisi
dicarloj 10:1163fb31b0a7 3
dicarloj 10:1163fb31b0a7 4 This program is free software; you can redistribute it and/or modify
dicarloj 10:1163fb31b0a7 5 it under the terms of the GNU General Public License as published by
dicarloj 10:1163fb31b0a7 6 the Free Software Foundation; either version 2 of the License , or
dicarloj 10:1163fb31b0a7 7 (at your option) any later version.
dicarloj 10:1163fb31b0a7 8
dicarloj 10:1163fb31b0a7 9 This program is distributed in the hope that it will be useful,
dicarloj 10:1163fb31b0a7 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
dicarloj 10:1163fb31b0a7 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dicarloj 10:1163fb31b0a7 12 GNU General Public License for more details.
dicarloj 10:1163fb31b0a7 13
dicarloj 10:1163fb31b0a7 14 You should have received a copy of the GNU General Public License
dicarloj 10:1163fb31b0a7 15 along with this program. If not, write to the Free Software
dicarloj 10:1163fb31b0a7 16 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
dicarloj 10:1163fb31b0a7 17 */
dicarloj 10:1163fb31b0a7 18
dicarloj 10:1163fb31b0a7 19
dicarloj 10:1163fb31b0a7 20 #include <stdio.h>
dicarloj 10:1163fb31b0a7 21 #include <stdlib.h>
dicarloj 10:1163fb31b0a7 22 #include <stdarg.h>
dicarloj 10:1163fb31b0a7 23 #include <string.h>
dicarloj 10:1163fb31b0a7 24 #include <ctype.h>
dicarloj 10:1163fb31b0a7 25 #include "main.h"
dicarloj 10:1163fb31b0a7 26
dicarloj 10:1163fb31b0a7 27 #define error(X) do { printf("ERROR: %s\n", X); } while (0)
dicarloj 10:1163fb31b0a7 28 #define out_buf_size 5000
dicarloj 10:1163fb31b0a7 29 #define in_buf_size 5000
dicarloj 10:1163fb31b0a7 30
dicarloj 10:1163fb31b0a7 31 int out_counter = 0;
dicarloj 10:1163fb31b0a7 32 int in_counter = 0;
dicarloj 10:1163fb31b0a7 33 char out_buf[out_buf_size];
dicarloj 10:1163fb31b0a7 34 char in_buf [in_buf_size];
dicarloj 10:1163fb31b0a7 35
dicarloj 10:1163fb31b0a7 36 char lisp_exit = 0;
dicarloj 10:1163fb31b0a7 37
dicarloj 10:1163fb31b0a7 38 void init_buf()
dicarloj 10:1163fb31b0a7 39 {
dicarloj 10:1163fb31b0a7 40 for(int i = 0; i < out_buf_size; i++)
dicarloj 10:1163fb31b0a7 41 out_buf[i] = 0;
dicarloj 10:1163fb31b0a7 42
dicarloj 10:1163fb31b0a7 43 for(int i = 0; i < in_buf_size; i++)
dicarloj 10:1163fb31b0a7 44 in_buf[i] = 0;
dicarloj 10:1163fb31b0a7 45
dicarloj 10:1163fb31b0a7 46 out_buf[out_buf_size - 1] = 0;
dicarloj 10:1163fb31b0a7 47 out_counter = 0;
dicarloj 10:1163fb31b0a7 48 in_counter = 0;
dicarloj 10:1163fb31b0a7 49 }
dicarloj 10:1163fb31b0a7 50
dicarloj 10:1163fb31b0a7 51 char getc_2()
dicarloj 10:1163fb31b0a7 52 {
dicarloj 10:1163fb31b0a7 53 //draw_vincent_string("getc2");
dicarloj 10:1163fb31b0a7 54 in_counter++;
dicarloj 10:1163fb31b0a7 55 if(in_counter >= in_buf_size)
dicarloj 10:1163fb31b0a7 56 {
dicarloj 10:1163fb31b0a7 57 lisp_exit = 1;
dicarloj 10:1163fb31b0a7 58 return EOF;
dicarloj 10:1163fb31b0a7 59 }
dicarloj 10:1163fb31b0a7 60
dicarloj 10:1163fb31b0a7 61 char next_char = in_buf[in_counter - 1];
dicarloj 10:1163fb31b0a7 62
dicarloj 10:1163fb31b0a7 63 if(next_char == 0)
dicarloj 10:1163fb31b0a7 64 {
dicarloj 10:1163fb31b0a7 65 lisp_exit = 1;
dicarloj 10:1163fb31b0a7 66 return EOF;
dicarloj 10:1163fb31b0a7 67 }
dicarloj 10:1163fb31b0a7 68
dicarloj 10:1163fb31b0a7 69 return in_buf[in_counter-1];
dicarloj 10:1163fb31b0a7 70 }
dicarloj 10:1163fb31b0a7 71
dicarloj 10:1163fb31b0a7 72 void ungetc_2(char c)
dicarloj 10:1163fb31b0a7 73 {
dicarloj 10:1163fb31b0a7 74 in_counter--;
dicarloj 10:1163fb31b0a7 75 }
dicarloj 10:1163fb31b0a7 76
dicarloj 10:1163fb31b0a7 77
dicarloj 10:1163fb31b0a7 78 char* strdup_2(char* in)
dicarloj 10:1163fb31b0a7 79 {
dicarloj 10:1163fb31b0a7 80 char* new_string = (char*)malloc(strlen(in));
dicarloj 10:1163fb31b0a7 81 strcpy(new_string,in);
dicarloj 10:1163fb31b0a7 82 return new_string;
dicarloj 10:1163fb31b0a7 83 }
dicarloj 10:1163fb31b0a7 84
dicarloj 10:1163fb31b0a7 85 void write_out(char* str)
dicarloj 10:1163fb31b0a7 86 {
dicarloj 10:1163fb31b0a7 87 printf("write_out: %s\n",str);
dicarloj 10:1163fb31b0a7 88
dicarloj 10:1163fb31b0a7 89 int len = strlen(str);
dicarloj 10:1163fb31b0a7 90
dicarloj 10:1163fb31b0a7 91 if(len + out_counter < out_buf_size)
dicarloj 10:1163fb31b0a7 92 {
dicarloj 10:1163fb31b0a7 93 printf("BUUFER OVERLFOW!\n");
dicarloj 10:1163fb31b0a7 94 return;
dicarloj 10:1163fb31b0a7 95 }
dicarloj 10:1163fb31b0a7 96
dicarloj 10:1163fb31b0a7 97 memcpy(out_buf + out_counter, str, len);
dicarloj 10:1163fb31b0a7 98 }
dicarloj 10:1163fb31b0a7 99
dicarloj 10:1163fb31b0a7 100 int line_num = 1;
dicarloj 10:1163fb31b0a7 101 int total_malloc = 0;
dicarloj 10:1163fb31b0a7 102
dicarloj 10:1163fb31b0a7 103 /*** List Structured Memory ***/
dicarloj 10:1163fb31b0a7 104 enum otype { INT, SYM, CONS, PROC, PRIMOP };
dicarloj 10:1163fb31b0a7 105 typedef struct obj {
dicarloj 10:1163fb31b0a7 106 enum otype type;
dicarloj 10:1163fb31b0a7 107 int line_num;
dicarloj 10:1163fb31b0a7 108 struct obj *p[1];
dicarloj 10:1163fb31b0a7 109 } obj;
dicarloj 10:1163fb31b0a7 110 typedef obj * (*primop)(obj *);
dicarloj 10:1163fb31b0a7 111 obj *all_symbols, *top_env, *nil, *tee, *quote,
dicarloj 10:1163fb31b0a7 112 *s_if, *s_lambda, *s_define, *s_setb, *s_begin;
dicarloj 10:1163fb31b0a7 113
dicarloj 10:1163fb31b0a7 114 #define cons(X, Y) omake(CONS, 2, (X), (Y))
dicarloj 10:1163fb31b0a7 115
dicarloj 10:1163fb31b0a7 116 obj *car(obj *X) {
dicarloj 10:1163fb31b0a7 117 if(X == 0) {
dicarloj 10:1163fb31b0a7 118 sprintf(out_buf + strlen(out_buf),"warning: car argument null on line %d\n", line_num);
dicarloj 10:1163fb31b0a7 119 return nil;
dicarloj 10:1163fb31b0a7 120 }
dicarloj 10:1163fb31b0a7 121 if(X == nil)
dicarloj 10:1163fb31b0a7 122 return nil;
dicarloj 10:1163fb31b0a7 123 if(X->type != CONS) {
dicarloj 10:1163fb31b0a7 124 sprintf(out_buf + strlen(out_buf),"warning: car argument not a list (%d) on line %d\n", X->p[0], X->line_num);
dicarloj 10:1163fb31b0a7 125 return nil;
dicarloj 10:1163fb31b0a7 126 }
dicarloj 10:1163fb31b0a7 127 return X->p[0];
dicarloj 10:1163fb31b0a7 128 }
dicarloj 10:1163fb31b0a7 129
dicarloj 10:1163fb31b0a7 130 obj *cdr(obj *X) {
dicarloj 10:1163fb31b0a7 131 if(X == nil)
dicarloj 10:1163fb31b0a7 132 return nil;
dicarloj 10:1163fb31b0a7 133 if(X->type != CONS) {
dicarloj 10:1163fb31b0a7 134 sprintf(out_buf + strlen(out_buf),"warning: cdr argument not a list on line %d\n", X->line_num);
dicarloj 10:1163fb31b0a7 135 return nil;
dicarloj 10:1163fb31b0a7 136 }
dicarloj 10:1163fb31b0a7 137 if(X->p[1] == 0) {
dicarloj 10:1163fb31b0a7 138 sprintf(out_buf + strlen(out_buf),"error: cdr list element is zero-pointer at %d\n", X->line_num);
dicarloj 10:1163fb31b0a7 139 return nil;
dicarloj 10:1163fb31b0a7 140 }
dicarloj 10:1163fb31b0a7 141 return X->p[1];
dicarloj 10:1163fb31b0a7 142 }
dicarloj 10:1163fb31b0a7 143
dicarloj 10:1163fb31b0a7 144 #define setcar(X,Y) (((X)->p[0]) = (Y))
dicarloj 10:1163fb31b0a7 145 #define setcdr(X,Y) (((X)->p[1]) = (Y))
dicarloj 10:1163fb31b0a7 146 #define mkint(X) omake(INT, 1, (obj *)(X))
dicarloj 10:1163fb31b0a7 147 #define intval(X) ((int)((X)->type == INT ? (X)->p[0] : 0)) // intval for INT only
dicarloj 10:1163fb31b0a7 148 #define mksym(X) omake(SYM, 1, (obj *)(X))
dicarloj 10:1163fb31b0a7 149 #define symname(X) ((char *)((X)->p[0]))
dicarloj 10:1163fb31b0a7 150 #define mkprimop(X) omake(PRIMOP, 1, (obj *)(X))
dicarloj 10:1163fb31b0a7 151 #define primopval(X) ((primop)(X)->p[0])
dicarloj 10:1163fb31b0a7 152 #define mkproc(X,Y,Z) omake(PROC, 3, (X), (Y), (Z))
dicarloj 10:1163fb31b0a7 153 #define procargs(X) ((X)->p[0])
dicarloj 10:1163fb31b0a7 154 #define proccode(X) ((X)->p[1])
dicarloj 10:1163fb31b0a7 155 #define procenv(X) ((X)->p[2])
dicarloj 10:1163fb31b0a7 156 #define isnil(X) ((X) == nil)
dicarloj 10:1163fb31b0a7 157
dicarloj 10:1163fb31b0a7 158 obj *omake(enum otype type, int count, ...) {
dicarloj 10:1163fb31b0a7 159 obj *ret;
dicarloj 10:1163fb31b0a7 160 va_list ap;
dicarloj 10:1163fb31b0a7 161 int i;
dicarloj 10:1163fb31b0a7 162 va_start(ap, count);
dicarloj 10:1163fb31b0a7 163 int object_size = sizeof(obj) + (count - 1)*sizeof(obj *);
dicarloj 10:1163fb31b0a7 164 total_malloc += object_size;
dicarloj 10:1163fb31b0a7 165 if(type == INT)
dicarloj 10:1163fb31b0a7 166 printf("malloc %d bytes for INT\r\n",object_size);
dicarloj 10:1163fb31b0a7 167 if(type == SYM)
dicarloj 10:1163fb31b0a7 168 printf("malloc %d bytes for SYM\r\n",object_size);
dicarloj 10:1163fb31b0a7 169 if(type == CONS)
dicarloj 10:1163fb31b0a7 170 printf("malloc %d bytes for CONS\r\n",object_size);
dicarloj 10:1163fb31b0a7 171 if(type == SYM)
dicarloj 10:1163fb31b0a7 172 printf("malloc %d bytes for PROC\r\n",object_size);
dicarloj 10:1163fb31b0a7 173 if(type == PRIMOP)
dicarloj 10:1163fb31b0a7 174 printf("malloc %d bytes for PRIMOP\r\n",object_size);
dicarloj 10:1163fb31b0a7 175
dicarloj 9:2a47b9ff8911 176 //enum otype { INT, SYM, CONS, PROC, PRIMOP };
dicarloj 10:1163fb31b0a7 177 ret = (obj *) malloc(object_size);
dicarloj 10:1163fb31b0a7 178 ret->type = type;
dicarloj 10:1163fb31b0a7 179 ret->line_num = line_num;
dicarloj 10:1163fb31b0a7 180 for(i = 0; i < count; i++) ret->p[i] = va_arg(ap, obj *);
dicarloj 10:1163fb31b0a7 181 va_end(ap);
dicarloj 10:1163fb31b0a7 182 return ret;
dicarloj 10:1163fb31b0a7 183 }
dicarloj 10:1163fb31b0a7 184
dicarloj 10:1163fb31b0a7 185 obj *findsym(char *name) {
dicarloj 10:1163fb31b0a7 186 obj *symlist;
dicarloj 10:1163fb31b0a7 187 for(symlist = all_symbols; !isnil(symlist); symlist = cdr(symlist))
dicarloj 10:1163fb31b0a7 188 if(!strcmp(name, symname(car(symlist))))
dicarloj 10:1163fb31b0a7 189 return symlist;
dicarloj 10:1163fb31b0a7 190 return nil;
dicarloj 10:1163fb31b0a7 191 }
dicarloj 10:1163fb31b0a7 192
dicarloj 10:1163fb31b0a7 193 obj *intern(char *name) {
dicarloj 10:1163fb31b0a7 194 obj *op = findsym(name);
dicarloj 10:1163fb31b0a7 195 if(!isnil(op)) return car(op);
dicarloj 10:1163fb31b0a7 196 op = mksym(name);
dicarloj 10:1163fb31b0a7 197 all_symbols = cons(op, all_symbols);
dicarloj 10:1163fb31b0a7 198 return op;
dicarloj 10:1163fb31b0a7 199 }
dicarloj 10:1163fb31b0a7 200
dicarloj 10:1163fb31b0a7 201 /*** Environment ***/
dicarloj 10:1163fb31b0a7 202 #define extend(ENV, SYM, VAL) (cons(cons((SYM), (VAL)), (ENV)))
dicarloj 10:1163fb31b0a7 203
dicarloj 10:1163fb31b0a7 204 obj *multiple_extend(obj *env, obj *syms, obj *vals) {
dicarloj 10:1163fb31b0a7 205 return isnil(syms) ?
dicarloj 10:1163fb31b0a7 206 env :
dicarloj 10:1163fb31b0a7 207 multiple_extend(extend(env, car(syms), car(vals)),
dicarloj 10:1163fb31b0a7 208 cdr(syms), cdr(vals));
dicarloj 10:1163fb31b0a7 209 }
dicarloj 10:1163fb31b0a7 210
dicarloj 10:1163fb31b0a7 211 obj *extend_top(obj *sym, obj *val) {
dicarloj 10:1163fb31b0a7 212 setcdr(top_env, cons(cons(sym, val), cdr(top_env)));
dicarloj 10:1163fb31b0a7 213 return val;
dicarloj 10:1163fb31b0a7 214 }
dicarloj 10:1163fb31b0a7 215
dicarloj 10:1163fb31b0a7 216 obj *assoc(obj *key, obj *alist) {
dicarloj 10:1163fb31b0a7 217 if(isnil(alist)) return nil;
dicarloj 10:1163fb31b0a7 218 if(car(car(alist)) == key) return car(alist);
dicarloj 10:1163fb31b0a7 219 return assoc(key, cdr(alist));
dicarloj 10:1163fb31b0a7 220 }
dicarloj 10:1163fb31b0a7 221
dicarloj 10:1163fb31b0a7 222 /*** Input/Output ***/
dicarloj 10:1163fb31b0a7 223 //FILE *ifp;
dicarloj 10:1163fb31b0a7 224 char *token_la;
dicarloj 10:1163fb31b0a7 225 int la_valid = 0;
dicarloj 10:1163fb31b0a7 226 #define MAXLEN 100
dicarloj 10:1163fb31b0a7 227 char buf[MAXLEN];
dicarloj 10:1163fb31b0a7 228 int bufused;
dicarloj 10:1163fb31b0a7 229
dicarloj 10:1163fb31b0a7 230 void add_to_buf(char ch) { if(bufused < MAXLEN - 1) buf[bufused++] = ch; }
dicarloj 10:1163fb31b0a7 231 char *buf2str() { buf[bufused++] = '\0'; return strdup_2(buf); }
dicarloj 10:1163fb31b0a7 232 //void setinput(FILE *fp) { ifp = fp; }
dicarloj 10:1163fb31b0a7 233 void putback_token(char *token) { token_la = token; la_valid = 1; }
dicarloj 10:1163fb31b0a7 234
dicarloj 10:1163fb31b0a7 235 void myexit(int code);
dicarloj 10:1163fb31b0a7 236
dicarloj 10:1163fb31b0a7 237 char *gettoken() {
dicarloj 10:1163fb31b0a7 238 int ch;
dicarloj 10:1163fb31b0a7 239 char comment=0;
dicarloj 10:1163fb31b0a7 240
dicarloj 10:1163fb31b0a7 241 bufused = 0;
dicarloj 10:1163fb31b0a7 242 if(la_valid) { la_valid = 0; return token_la; }
dicarloj 10:1163fb31b0a7 243 do {
dicarloj 10:1163fb31b0a7 244 if((ch = getc_2()) == EOF) {myexit(0); return NULL;} // replace with serial
dicarloj 10:1163fb31b0a7 245 //draw_vincent_string("gettoken");
dicarloj 10:1163fb31b0a7 246 if(ch == ';') comment = 1;
dicarloj 10:1163fb31b0a7 247 if(ch == '\n') {
dicarloj 10:1163fb31b0a7 248 comment = 0;
dicarloj 10:1163fb31b0a7 249 line_num++;
dicarloj 10:1163fb31b0a7 250 }
dicarloj 10:1163fb31b0a7 251
dicarloj 10:1163fb31b0a7 252 } while(isspace(ch) || comment);
dicarloj 10:1163fb31b0a7 253
dicarloj 10:1163fb31b0a7 254
dicarloj 10:1163fb31b0a7 255 add_to_buf(ch);
dicarloj 10:1163fb31b0a7 256 if(strchr("()\'", ch)) return buf2str();
dicarloj 10:1163fb31b0a7 257 for(;;) {
dicarloj 10:1163fb31b0a7 258 if(lisp_exit) { return NULL; }
dicarloj 10:1163fb31b0a7 259 if((ch = getc_2()) == EOF) {myexit(0); return NULL;}
dicarloj 10:1163fb31b0a7 260 if(strchr("()\'", ch) || isspace(ch)) {
dicarloj 10:1163fb31b0a7 261 ungetc_2(ch);
dicarloj 10:1163fb31b0a7 262 return buf2str();
dicarloj 10:1163fb31b0a7 263 }
dicarloj 10:1163fb31b0a7 264 add_to_buf(ch);
dicarloj 10:1163fb31b0a7 265 }
dicarloj 10:1163fb31b0a7 266 }
dicarloj 10:1163fb31b0a7 267
dicarloj 10:1163fb31b0a7 268 obj *readlist();
dicarloj 10:1163fb31b0a7 269
dicarloj 10:1163fb31b0a7 270 obj *readobj() {
dicarloj 10:1163fb31b0a7 271 char *token;
dicarloj 10:1163fb31b0a7 272
dicarloj 10:1163fb31b0a7 273 token = gettoken();
dicarloj 10:1163fb31b0a7 274 if(token == NULL) return NULL;
dicarloj 10:1163fb31b0a7 275 if(!strcmp(token, "(")) return readlist();
dicarloj 10:1163fb31b0a7 276 if(!strcmp(token, "\'")) return cons(quote, cons(readobj(), nil));
dicarloj 10:1163fb31b0a7 277
dicarloj 10:1163fb31b0a7 278 if(token[strspn(token, "0123456789")] == '\0'
dicarloj 10:1163fb31b0a7 279 || (token[0] == '-' && strlen(token) > 1))
dicarloj 10:1163fb31b0a7 280 return mkint(atoi(token));
dicarloj 10:1163fb31b0a7 281 return intern(token);
dicarloj 10:1163fb31b0a7 282 }
dicarloj 10:1163fb31b0a7 283
dicarloj 10:1163fb31b0a7 284 obj *readlist() {
dicarloj 10:1163fb31b0a7 285 char *token = gettoken();
dicarloj 10:1163fb31b0a7 286 if(token == NULL) return NULL;
dicarloj 10:1163fb31b0a7 287 obj *tmp;
dicarloj 10:1163fb31b0a7 288 if(!strcmp(token, ")")) return nil;
dicarloj 10:1163fb31b0a7 289 if(!strcmp(token, ".")) {
dicarloj 10:1163fb31b0a7 290 tmp = readobj();
dicarloj 10:1163fb31b0a7 291 if(strcmp(gettoken(), ")")) myexit(1);
dicarloj 10:1163fb31b0a7 292 return tmp;
dicarloj 10:1163fb31b0a7 293 }
dicarloj 10:1163fb31b0a7 294 putback_token(token);
dicarloj 10:1163fb31b0a7 295 tmp = readobj(); /* Must force evaluation order */
dicarloj 10:1163fb31b0a7 296 return cons(tmp, readlist());
dicarloj 10:1163fb31b0a7 297 }
dicarloj 10:1163fb31b0a7 298
dicarloj 10:1163fb31b0a7 299 void writeobj(obj *op) {
dicarloj 10:1163fb31b0a7 300
dicarloj 10:1163fb31b0a7 301 if(op == NULL) { return; }
dicarloj 10:1163fb31b0a7 302 switch(op->type) {
dicarloj 10:1163fb31b0a7 303 case INT: sprintf(out_buf + strlen(out_buf),"%d", intval(op)); break;
dicarloj 10:1163fb31b0a7 304 case CONS:
dicarloj 10:1163fb31b0a7 305 //draw_vincent_string(" write_cons ");
dicarloj 10:1163fb31b0a7 306 sprintf(out_buf + strlen(out_buf),"(");
dicarloj 10:1163fb31b0a7 307 for(;;) {
dicarloj 10:1163fb31b0a7 308 writeobj(car(op));
dicarloj 10:1163fb31b0a7 309 if(isnil(cdr(op))) {
dicarloj 10:1163fb31b0a7 310 sprintf(out_buf + strlen(out_buf),")");
dicarloj 10:1163fb31b0a7 311 break;
dicarloj 10:1163fb31b0a7 312 }
dicarloj 10:1163fb31b0a7 313 op = cdr(op);
dicarloj 10:1163fb31b0a7 314 if(op->type != CONS) {
dicarloj 10:1163fb31b0a7 315 sprintf(out_buf + strlen(out_buf)," . ");
dicarloj 10:1163fb31b0a7 316 writeobj(op);
dicarloj 10:1163fb31b0a7 317 sprintf(out_buf + strlen(out_buf),")");
dicarloj 10:1163fb31b0a7 318 break;
dicarloj 10:1163fb31b0a7 319 }
dicarloj 10:1163fb31b0a7 320 sprintf(out_buf + strlen(out_buf)," ");
dicarloj 10:1163fb31b0a7 321 }
dicarloj 10:1163fb31b0a7 322 break;
dicarloj 10:1163fb31b0a7 323 case SYM:
dicarloj 10:1163fb31b0a7 324
dicarloj 10:1163fb31b0a7 325 if(isnil(op)) sprintf(out_buf + strlen(out_buf),"()");
dicarloj 10:1163fb31b0a7 326 else sprintf(out_buf + strlen(out_buf),"%s", symname(op));
dicarloj 10:1163fb31b0a7 327 break;
dicarloj 10:1163fb31b0a7 328 case PRIMOP: sprintf(out_buf + strlen(out_buf),"#<PRIMOP>"); break;
dicarloj 10:1163fb31b0a7 329 case PROC: sprintf(out_buf + strlen(out_buf),"#<PROC>"); break;
dicarloj 10:1163fb31b0a7 330 default: myexit(1);
dicarloj 10:1163fb31b0a7 331 }
dicarloj 10:1163fb31b0a7 332 }
dicarloj 10:1163fb31b0a7 333
dicarloj 10:1163fb31b0a7 334 /*** Evaluator (Eval/no Apply) ***/
dicarloj 10:1163fb31b0a7 335 obj *evlis(obj *exps, obj *env);
dicarloj 10:1163fb31b0a7 336
dicarloj 10:1163fb31b0a7 337 obj *eval(obj *exp, obj *env) {
dicarloj 10:1163fb31b0a7 338 if(lisp_exit) return NULL;
dicarloj 10:1163fb31b0a7 339 obj *tmp, *proc, *vals;
dicarloj 10:1163fb31b0a7 340
dicarloj 10:1163fb31b0a7 341 eval_start:
dicarloj 10:1163fb31b0a7 342
dicarloj 10:1163fb31b0a7 343 if(exp == NULL) return nil;
dicarloj 10:1163fb31b0a7 344 if(exp == nil) return nil;
dicarloj 10:1163fb31b0a7 345
dicarloj 10:1163fb31b0a7 346
dicarloj 10:1163fb31b0a7 347 switch(exp->type) {
dicarloj 10:1163fb31b0a7 348 case INT: return exp;
dicarloj 10:1163fb31b0a7 349 case SYM: tmp = assoc(exp, env);
dicarloj 10:1163fb31b0a7 350
dicarloj 10:1163fb31b0a7 351 if(tmp == nil) {
dicarloj 10:1163fb31b0a7 352 sprintf(out_buf + strlen(out_buf), "Unbound symbol ");
dicarloj 10:1163fb31b0a7 353 writeobj(exp);
dicarloj 10:1163fb31b0a7 354 sprintf(out_buf + strlen(out_buf), "\n");
dicarloj 10:1163fb31b0a7 355 return nil;
dicarloj 10:1163fb31b0a7 356 }
dicarloj 10:1163fb31b0a7 357 return cdr(tmp);
dicarloj 10:1163fb31b0a7 358
dicarloj 10:1163fb31b0a7 359
dicarloj 10:1163fb31b0a7 360
dicarloj 10:1163fb31b0a7 361 case CONS:
dicarloj 10:1163fb31b0a7 362 if(car(exp) == s_if) {
dicarloj 10:1163fb31b0a7 363 if(eval(car(cdr(exp)), env) != nil)
dicarloj 10:1163fb31b0a7 364 return eval(car(cdr(cdr(exp))), env);
dicarloj 10:1163fb31b0a7 365 else
dicarloj 10:1163fb31b0a7 366 return eval(car(cdr(cdr(cdr(exp)))), env);
dicarloj 10:1163fb31b0a7 367 }
dicarloj 10:1163fb31b0a7 368 if(car(exp) == s_lambda)
dicarloj 10:1163fb31b0a7 369 return mkproc(car(cdr(exp)), cdr(cdr(exp)), env);
dicarloj 10:1163fb31b0a7 370 if(car(exp) == quote)
dicarloj 10:1163fb31b0a7 371 return car(cdr(exp));
dicarloj 10:1163fb31b0a7 372 if(car(exp) == s_define)
dicarloj 10:1163fb31b0a7 373 return(extend_top(car(cdr(exp)),
dicarloj 10:1163fb31b0a7 374 eval(car(cdr(cdr(exp))), env)));
dicarloj 10:1163fb31b0a7 375 if(car(exp) == s_setb) {
dicarloj 10:1163fb31b0a7 376 obj *pair = assoc(car(cdr(exp)), env);
dicarloj 10:1163fb31b0a7 377 obj *newval = eval(car(cdr(cdr(exp))), env);
dicarloj 10:1163fb31b0a7 378 setcdr(pair, newval);
dicarloj 10:1163fb31b0a7 379 return newval;
dicarloj 10:1163fb31b0a7 380 }
dicarloj 10:1163fb31b0a7 381 if(car(exp) == s_begin) {
dicarloj 10:1163fb31b0a7 382 exp = cdr(exp);
dicarloj 10:1163fb31b0a7 383 if(exp == nil) return nil;
dicarloj 10:1163fb31b0a7 384 for(;;) {
dicarloj 10:1163fb31b0a7 385 if(cdr(exp) == nil) {
dicarloj 10:1163fb31b0a7 386 exp = car(exp);
dicarloj 10:1163fb31b0a7 387 goto eval_start;
dicarloj 10:1163fb31b0a7 388 }
dicarloj 10:1163fb31b0a7 389 eval(car(exp), env);
dicarloj 10:1163fb31b0a7 390 exp = cdr(exp);
dicarloj 10:1163fb31b0a7 391 }
dicarloj 10:1163fb31b0a7 392 }
dicarloj 10:1163fb31b0a7 393 proc = eval(car(exp), env);
dicarloj 10:1163fb31b0a7 394 vals = evlis(cdr(exp), env);
dicarloj 10:1163fb31b0a7 395 if(proc->type == PRIMOP)
dicarloj 10:1163fb31b0a7 396 return (*primopval(proc))(vals);
dicarloj 10:1163fb31b0a7 397 if(proc->type == PROC) {
dicarloj 10:1163fb31b0a7 398 /* For dynamic scope, use env instead of procenv(proc) */
dicarloj 10:1163fb31b0a7 399 env = multiple_extend(procenv(proc), procargs(proc), vals);
dicarloj 10:1163fb31b0a7 400 exp = cons(s_begin, proccode(proc));
dicarloj 10:1163fb31b0a7 401 goto eval_start;
dicarloj 10:1163fb31b0a7 402 }
dicarloj 10:1163fb31b0a7 403 sprintf(out_buf + strlen(out_buf),"Bad PROC type\n");
dicarloj 10:1163fb31b0a7 404 return nil;
dicarloj 10:1163fb31b0a7 405 case PRIMOP: return exp;
dicarloj 10:1163fb31b0a7 406 case PROC: return exp;
dicarloj 10:1163fb31b0a7 407 }
dicarloj 10:1163fb31b0a7 408 /* Not reached */
dicarloj 10:1163fb31b0a7 409 return exp;
dicarloj 10:1163fb31b0a7 410 }
dicarloj 10:1163fb31b0a7 411
dicarloj 10:1163fb31b0a7 412 obj *evlis(obj *exps, obj *env) {
dicarloj 10:1163fb31b0a7 413 if(exps == nil) return nil;
dicarloj 10:1163fb31b0a7 414 return cons(eval(car(exps), env),
dicarloj 10:1163fb31b0a7 415 evlis(cdr(exps), env));
dicarloj 10:1163fb31b0a7 416 }
dicarloj 10:1163fb31b0a7 417
dicarloj 10:1163fb31b0a7 418 /*** Primitives ***/
dicarloj 10:1163fb31b0a7 419 obj *prim_sum(obj *args) {
dicarloj 10:1163fb31b0a7 420 int sum;
dicarloj 10:1163fb31b0a7 421 for(sum = 0; !isnil(args); sum += intval(car(args)), args = cdr(args));
dicarloj 10:1163fb31b0a7 422 return mkint(sum);
dicarloj 10:1163fb31b0a7 423 }
dicarloj 10:1163fb31b0a7 424
dicarloj 10:1163fb31b0a7 425 obj *prim_sub(obj *args) {
dicarloj 10:1163fb31b0a7 426 int sum;
dicarloj 10:1163fb31b0a7 427 for(sum = intval(car(args)), args = cdr(args);
dicarloj 10:1163fb31b0a7 428 !isnil(args);
dicarloj 10:1163fb31b0a7 429 sum -= intval(car(args)), args = cdr(args));
dicarloj 10:1163fb31b0a7 430 return mkint(sum);
dicarloj 10:1163fb31b0a7 431 }
dicarloj 10:1163fb31b0a7 432
dicarloj 10:1163fb31b0a7 433 obj *prim_prod(obj *args) {
dicarloj 10:1163fb31b0a7 434 int prod;
dicarloj 10:1163fb31b0a7 435 for(prod = 1; !isnil(args); prod *= intval(car(args)), args = cdr(args));
dicarloj 10:1163fb31b0a7 436 return mkint(prod);
dicarloj 10:1163fb31b0a7 437 }
dicarloj 10:1163fb31b0a7 438 obj *prim_divide(obj *args) {
dicarloj 10:1163fb31b0a7 439 int prod = intval(car(args));
dicarloj 10:1163fb31b0a7 440 args = cdr(args);
dicarloj 10:1163fb31b0a7 441 while(!isnil(args)) {
dicarloj 10:1163fb31b0a7 442 prod /= intval(car(args));
dicarloj 10:1163fb31b0a7 443 args = cdr(args);
dicarloj 10:1163fb31b0a7 444 }
dicarloj 10:1163fb31b0a7 445
dicarloj 10:1163fb31b0a7 446 return mkint(prod);
dicarloj 10:1163fb31b0a7 447 }
dicarloj 10:1163fb31b0a7 448
dicarloj 10:1163fb31b0a7 449 obj *prim_gt(obj *args) {
dicarloj 10:1163fb31b0a7 450 return intval(car(args)) > intval(car(cdr(args))) ? tee : nil;
dicarloj 10:1163fb31b0a7 451 }
dicarloj 10:1163fb31b0a7 452
dicarloj 10:1163fb31b0a7 453 obj *prim_lt(obj *args) {
dicarloj 10:1163fb31b0a7 454 return intval(car(args)) < intval(car(cdr(args))) ? tee : nil;
dicarloj 10:1163fb31b0a7 455 }
dicarloj 10:1163fb31b0a7 456 obj *prim_ge(obj *args) {
dicarloj 10:1163fb31b0a7 457 return intval(car(args)) >= intval(car(cdr(args))) ? tee : nil;
dicarloj 10:1163fb31b0a7 458 }
dicarloj 10:1163fb31b0a7 459 obj *prim_le(obj *args) {
dicarloj 10:1163fb31b0a7 460 return intval(car(args)) <= intval(car(cdr(args))) ? tee : nil;
dicarloj 10:1163fb31b0a7 461 }
dicarloj 10:1163fb31b0a7 462 obj *prim_numeq(obj *args) {
dicarloj 10:1163fb31b0a7 463 return intval(car(args)) == intval(car(cdr(args))) ? tee : nil;
dicarloj 10:1163fb31b0a7 464 }
dicarloj 10:1163fb31b0a7 465
dicarloj 10:1163fb31b0a7 466 obj *prim_cons(obj *args) { return cons(car(args), car(cdr(args))); }
dicarloj 10:1163fb31b0a7 467 obj *prim_car(obj *args) { return car(car(args)); }
dicarloj 10:1163fb31b0a7 468 obj *prim_cdr(obj *args) { return cdr(car(args)); }
dicarloj 10:1163fb31b0a7 469
dicarloj 10:1163fb31b0a7 470
dicarloj 10:1163fb31b0a7 471 /*** Helpers *****/
dicarloj 10:1163fb31b0a7 472
dicarloj 10:1163fb31b0a7 473 obj *prim_print(obj *args) {
dicarloj 10:1163fb31b0a7 474 while(!isnil(args)) {
dicarloj 10:1163fb31b0a7 475 writeobj(car(args));
dicarloj 10:1163fb31b0a7 476 args = cdr(args);
dicarloj 10:1163fb31b0a7 477 sprintf(out_buf + strlen(out_buf)," ");
dicarloj 10:1163fb31b0a7 478 }
dicarloj 10:1163fb31b0a7 479 sprintf(out_buf + strlen(out_buf),"\n");
dicarloj 10:1163fb31b0a7 480 return nil;
dicarloj 10:1163fb31b0a7 481 }
dicarloj 10:1163fb31b0a7 482
dicarloj 10:1163fb31b0a7 483 /*** Initialization ***/
dicarloj 10:1163fb31b0a7 484 void init_sl3() {
dicarloj 10:1163fb31b0a7 485 nil = mksym("nil");
dicarloj 10:1163fb31b0a7 486 all_symbols = cons(nil, nil);
dicarloj 10:1163fb31b0a7 487 top_env = cons(cons(nil, nil), nil);
dicarloj 10:1163fb31b0a7 488 tee = intern("t");
dicarloj 10:1163fb31b0a7 489 extend_top(tee, tee);
dicarloj 10:1163fb31b0a7 490 quote = intern("quote");
dicarloj 10:1163fb31b0a7 491 s_if = intern("if");
dicarloj 10:1163fb31b0a7 492 s_lambda = intern("lambda");
dicarloj 10:1163fb31b0a7 493 s_define = intern("define");
dicarloj 10:1163fb31b0a7 494 s_setb = intern("set!");
dicarloj 10:1163fb31b0a7 495 s_begin = intern("begin");
dicarloj 10:1163fb31b0a7 496 extend_top(intern("+"), mkprimop(prim_sum));
dicarloj 10:1163fb31b0a7 497 extend_top(intern("-"), mkprimop(prim_sub));
dicarloj 10:1163fb31b0a7 498 extend_top(intern("*"), mkprimop(prim_prod));
dicarloj 10:1163fb31b0a7 499 extend_top(intern("/"), mkprimop(prim_divide));
dicarloj 10:1163fb31b0a7 500 extend_top(intern("="), mkprimop(prim_numeq));
dicarloj 10:1163fb31b0a7 501
dicarloj 10:1163fb31b0a7 502 extend_top(intern(">"), mkprimop(prim_gt));
dicarloj 10:1163fb31b0a7 503 extend_top(intern(">="), mkprimop(prim_ge));
dicarloj 10:1163fb31b0a7 504
dicarloj 10:1163fb31b0a7 505 extend_top(intern("<"), mkprimop(prim_lt));
dicarloj 10:1163fb31b0a7 506 extend_top(intern("<="), mkprimop(prim_le));
dicarloj 10:1163fb31b0a7 507
dicarloj 10:1163fb31b0a7 508 extend_top(intern("cons"), mkprimop(prim_cons));
dicarloj 10:1163fb31b0a7 509 extend_top(intern("car"), mkprimop(prim_car));
dicarloj 10:1163fb31b0a7 510 extend_top(intern("cdr"), mkprimop(prim_cdr));
dicarloj 10:1163fb31b0a7 511
dicarloj 10:1163fb31b0a7 512 extend_top(intern("print"), mkprimop(prim_print));
dicarloj 10:1163fb31b0a7 513 }
dicarloj 10:1163fb31b0a7 514
dicarloj 10:1163fb31b0a7 515 char* get_output()
dicarloj 10:1163fb31b0a7 516 {
dicarloj 10:1163fb31b0a7 517 return out_buf;
dicarloj 10:1163fb31b0a7 518 }
dicarloj 10:1163fb31b0a7 519
dicarloj 10:1163fb31b0a7 520 int lisp_init = 0;
dicarloj 10:1163fb31b0a7 521
dicarloj 10:1163fb31b0a7 522 /*** Main Driver ***/
dicarloj 10:1163fb31b0a7 523 int run_lisp(char* input) {
dicarloj 10:1163fb31b0a7 524 if(!lisp_init)
dicarloj 10:1163fb31b0a7 525 {
dicarloj 10:1163fb31b0a7 526 init_sl3();
dicarloj 10:1163fb31b0a7 527 lisp_init = 1;
dicarloj 10:1163fb31b0a7 528 }
dicarloj 10:1163fb31b0a7 529
dicarloj 10:1163fb31b0a7 530 init_buf();
dicarloj 10:1163fb31b0a7 531
dicarloj 10:1163fb31b0a7 532
dicarloj 10:1163fb31b0a7 533 lisp_exit = 0;
dicarloj 10:1163fb31b0a7 534 strcpy(in_buf, input);
dicarloj 10:1163fb31b0a7 535 if(!strncmp(input,"clear",4)){ clear_all_text(); return 0; }
dicarloj 10:1163fb31b0a7 536 if(!strncmp(input,"mem",3))
dicarloj 10:1163fb31b0a7 537 {
dicarloj 10:1163fb31b0a7 538 char memuse[40];
dicarloj 10:1163fb31b0a7 539 sprintf(memuse,"MEM: %d bytes",total_malloc);
dicarloj 10:1163fb31b0a7 540 draw_vincent_string(memuse);
dicarloj 10:1163fb31b0a7 541 return;
dicarloj 10:1163fb31b0a7 542 }
dicarloj 10:1163fb31b0a7 543 in_buf[in_buf_size - 1] = 0;
dicarloj 10:1163fb31b0a7 544 //new_line();
dicarloj 10:1163fb31b0a7 545 //draw_vincent_string(in_buf);
dicarloj 10:1163fb31b0a7 546 //new_line();
dicarloj 10:1163fb31b0a7 547 //print_vincent_string(in_buf);
dicarloj 10:1163fb31b0a7 548 // if(argc == 2)
dicarloj 10:1163fb31b0a7 549 // {
dicarloj 10:1163fb31b0a7 550 // memcpy(in_buf,argv[1],strlen(argv[1]));
dicarloj 10:1163fb31b0a7 551 // printf("%s\n",in_buf);
dicarloj 9:2a47b9ff8911 552 // }
dicarloj 10:1163fb31b0a7 553 // else
dicarloj 10:1163fb31b0a7 554 //sprintf(in_buf,"(+ 2 2)\n");
dicarloj 10:1163fb31b0a7 555 // char test_in[] = "(+ 2 2)\n";
dicarloj 10:1163fb31b0a7 556 // FILE* input_stream = open_memstream(test_in,8);
dicarloj 10:1163fb31b0a7 557 // fprintf(input_stream,"(+ 2 3)\n");
dicarloj 10:1163fb31b0a7 558 // char test_out[50];
dicarloj 10:1163fb31b0a7 559 // FILE* output_stream = fmemopen(test_out,50,"w");
dicarloj 10:1163fb31b0a7 560 //setinput(input_stream);
dicarloj 10:1163fb31b0a7 561 int lisp_count = 0;
dicarloj 10:1163fb31b0a7 562 while(!lisp_exit) {
dicarloj 10:1163fb31b0a7 563 writeobj(eval(readobj(), top_env));
dicarloj 10:1163fb31b0a7 564 //fflush(output_stream);
dicarloj 10:1163fb31b0a7 565 printf("\n");
dicarloj 10:1163fb31b0a7 566 printf("%s\n",out_buf);
dicarloj 10:1163fb31b0a7 567
dicarloj 10:1163fb31b0a7 568 lisp_count++;
dicarloj 10:1163fb31b0a7 569 if(lisp_count > 500) break;
dicarloj 10:1163fb31b0a7 570 //printf("outstream: %s\n",test_out);
dicarloj 10:1163fb31b0a7 571 }
dicarloj 10:1163fb31b0a7 572 draw_vincent_string(out_buf);
dicarloj 10:1163fb31b0a7 573 //draw_vincent_string("done!");
dicarloj 10:1163fb31b0a7 574 return 0;
dicarloj 10:1163fb31b0a7 575 }
dicarloj 10:1163fb31b0a7 576
dicarloj 10:1163fb31b0a7 577 void myexit(int code) {
dicarloj 10:1163fb31b0a7 578 printf("%d bytes left hanging\n", total_malloc);
dicarloj 10:1163fb31b0a7 579 lisp_exit = 1;
dicarloj 10:1163fb31b0a7 580 }