Guest User

thp

a guest
Mar 26th, 2015
266
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.32 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5.  
  6. #define nil 0
  7.  
  8. enum
  9. {
  10.     Nil = 0,
  11.     List = 1,
  12.     Atom = 2,
  13.     ATOMSZ = 64,
  14. };
  15.  
  16. typedef struct O O;
  17.  
  18. struct O
  19. {
  20.     union {
  21.         O *o[2];
  22.         char *a;
  23.     };
  24.     int type;
  25. };
  26.  
  27. char *atomstr(O *o);
  28. O *mka(char *c);
  29. O *cons(O *car, O *cdr);
  30. O *car(O *o);
  31. O *cdr(O *o);
  32. O *r(void);
  33. void prin1(O *o);
  34. void pl(O *o[2], int paren);
  35. O *eval(O *o, O *env);
  36.  
  37. char *
  38. atomstr(O *o)
  39. {
  40.     if(o == nil)
  41.         return "";
  42.     if(o->type != Atom)
  43.         return "";
  44.  
  45.     return o->a;
  46. }
  47.  
  48. O *
  49. mka(char *c)
  50. {
  51.     O *o;
  52.  
  53.     o = malloc(sizeof(O));
  54.  
  55.     o->a = c;
  56.     o->type = Atom;
  57.     return o;
  58. }
  59.  
  60. O *
  61. cons(O *car, O *cdr)
  62. {
  63.     O *o;
  64.  
  65.     o = malloc(sizeof(O));
  66.  
  67.     o->o[0] = car;
  68.     o->o[1] = cdr;
  69.     o->type = List;
  70.  
  71.     return o;
  72. }
  73.  
  74. O *
  75. car(O *o)
  76. {
  77.     if(o == nil)
  78.         return nil;
  79.     if(o->type != List)
  80.         return nil;
  81.  
  82.     return o->o[0];
  83. }
  84.  
  85. O *
  86. cdr(O *o)
  87. {
  88.     if(o == nil)
  89.         return nil;
  90.     if(o->type != List)
  91.         return nil;
  92.  
  93.     return o->o[1];
  94. }
  95.  
  96. int
  97. skipspace(void)
  98. {
  99.     int c;
  100.  
  101.     while((c = getc(stdin)) >= 0){
  102.         if(!isspace(c))
  103.             break;
  104.     }
  105.     return c;
  106. }
  107.  
  108. O *
  109. rdatom(int c)
  110. {
  111.     int i;
  112.     char *s;
  113.  
  114.     s = malloc(ATOMSZ + 1);
  115.     if(s == nil)
  116.         return nil;
  117.  
  118.     for(i = 0; i < ATOMSZ; ++i){
  119.         if(!isgraph(c) || c == '(' || c == ')')
  120.             break;
  121.         s[i] = c;
  122.         c = getc(stdin);
  123.     }
  124.     ungetc(c, stdin);
  125.     s[i] = '\0';
  126.  
  127.     if(i == 0){
  128.         free(s);
  129.         return nil;
  130.     }
  131.     return mka(s);
  132. }
  133.  
  134. O *
  135. rdlist(void)
  136. {
  137.     O *car, *cdr;
  138.     int c;
  139.  
  140.     c = skipspace();
  141.  
  142.     if(c == ')')
  143.         return nil;
  144.  
  145.     ungetc(c, stdin);
  146.  
  147.     car = r();
  148.     c = skipspace();
  149.     if(c == '.'){
  150.         cdr = r();
  151.         c = skipspace();
  152.         if(c != ')')
  153.             return nil;
  154.         return cons(car, cdr);
  155.     }else{
  156.         ungetc(c, stdin);
  157.         cdr = rdlist();
  158.         return cons(car, cdr);
  159.     }
  160. }
  161.  
  162. O *
  163. r(void)
  164. {
  165.     int c;
  166.  
  167.     c = skipspace();
  168.  
  169.     if(c == '(')
  170.         return rdlist();
  171.     if(!isprint(c) || c == ')')
  172.         return nil;
  173.     return rdatom(c);
  174. }
  175.  
  176. /* XXX should it take o, or o->o[2] ? */
  177. void
  178. pl(O *o[2], int paren)
  179. {
  180.     if(o == nil)
  181.         return;
  182.  
  183.     if(paren)
  184.         printf("(");
  185.  
  186.     prin1(o[0]);
  187.  
  188.     if(o[1] == nil)
  189.         goto end;
  190.     switch(o[1]->type){
  191.     case Nil:
  192.         break;
  193.     case List:
  194.         printf(" ");
  195.         pl(o[1]->o, 0);
  196.         break;
  197.     case Atom:
  198.         printf(" . ");
  199.         prin1(o[1]);
  200.         break;
  201.     }
  202.  
  203. end:
  204.     if(paren)
  205.         printf(")");
  206. }
  207.  
  208. /* XXX externally-consumable prin1 should wrap this and bioflush, */
  209. /* XXX so we can bioprint inside.  (bioflush unsuitable; equiv to print() since recursive.) */
  210. void
  211. prin1(O *o)
  212. {
  213.     if(o == nil){
  214.         printf("nil");
  215.         return;
  216.     }
  217.     switch(o->type){
  218.     case Nil:
  219.         printf("nil");
  220.         return;
  221.     case List:
  222.         pl(o->o, 1);
  223.         return;
  224.     case Atom:
  225.         printf("%s", o->a);
  226.         return;
  227.     default:
  228.         printf("invalid type");
  229.         return;
  230.     }
  231. }
  232.  
  233.  
  234. /* XXX need to distinguish numbers. */
  235. O *
  236. evala(O *o, O *env)
  237. {
  238.     O *v;
  239.     char *a;
  240.  
  241.     if(o == nil)
  242.         return nil;
  243.     if(o->type != Atom)
  244.         return nil;
  245.  
  246.     a = atomstr(o);
  247.  
  248.     for(v = env; v != nil; v = cdr(v)){
  249.         if(strcmp(atomstr(car(car(v))), a) == 0)
  250.             return car(cdr(car(v)));
  251.     }
  252.     return o;
  253. }
  254.  
  255. O *
  256. evalargs(O *o, O *env)
  257. {
  258.     if(o == nil)
  259.         return nil;
  260.     if(o->type != List)
  261.         return o;
  262.  
  263.     return cons(eval(car(o), env), evalargs(cdr(o), env));
  264. }
  265.  
  266. //O *
  267. //args2env(O *proto, O *args, O *env)
  268. //{
  269. //  while(proto != nil){
  270. //      env = cons(cons(car(proto), cons(car(args), nil)), env);
  271. //      proto = cdr(proto);
  272. //      args = cdr(args);
  273. //  }
  274. //
  275. //  return env;
  276. //}
  277.  
  278. /* XXX how to do partial application? */
  279. O *
  280. args2env(O *proto, O *args, O *env)
  281. {
  282.     if(proto == nil)
  283.         return env;
  284.  
  285.     return cons(cons(car(proto), cons(car(args), nil)), args2env(cdr(proto), cdr(args), env));
  286. }
  287.  
  288. /* XXX expensive */
  289. O *
  290. splice(O *head, O *tail)
  291. {
  292.     if(head == nil)
  293.         return tail;
  294.     return cons(car(head), splice(cdr(head), tail));
  295. }
  296.  
  297. O *
  298. lambda(O *o, O *env)
  299. {
  300.     O *f, *args;
  301.  
  302.     if(o == nil)
  303.         return nil;
  304.  
  305.     f = car(o);
  306.     if(f == nil)
  307.         return nil;
  308.     if(f->type != List)
  309.         return nil;
  310.  
  311.     if(strcmp(atomstr(car(f)), "CLOSURE") == 0){
  312.         env =  splice(car(cdr(f)), env); /* XXX expensive! especially on every function call! */
  313.         args = evalargs(cdr(o), env);
  314.         printf("closure args: "); prin1(args); printf("\n");
  315.         env = args2env(car(cdr(cdr(f))), args, env);
  316.         return eval(car(cdr(cdr(cdr(f)))), env);
  317.     }
  318.  
  319.     if(strcmp(atomstr(car(f)), "LAMBDA") == 0){
  320.         args = evalargs(cdr(o), env);
  321.         printf("lambda args: "); prin1(args); printf("\n");
  322.         env = args2env(car(cdr(f)), args, env);
  323.         //print("env: "); prin1(env); print("\n");
  324.         //print("body: "); prin1(cdr(cdr(f))); print("\n");
  325.         //print("evaling body: "); prin1(eval(cdr(cdr(f)), env)); print("\n");
  326.         return eval(car(cdr(cdr(f))), env);
  327.     }
  328.  
  329.     printf("reached bottom of lambda\n");
  330.     return nil;
  331. }
  332.  
  333. /* (NAME (alist)) */
  334. /* Need to pass a list of local variables. */
  335. /* Need to handle all special forms here.  def/defun cond lambda let */
  336. /* Default case: lookup a in local variable list. */
  337. /* XXX closures! */
  338. /* XXX need to eval args! eg (let ((a (+ 1 2))) ...) */
  339. O *
  340. eval(O *o, O *env)
  341. {
  342.     char *a;
  343.     O *vars;
  344.  
  345.     if(o == nil)
  346.         return nil;
  347.     if(o->type != List)
  348.         return evala(o, env);
  349.  
  350.     o = cons(eval(car(o), env), cdr(o));
  351.  
  352.     if(car(o) != nil && car(o)->type == List)
  353.         return lambda(o, env);
  354.  
  355.     a = atomstr(car(o));
  356.  
  357.     if(strcmp(a, "CLOSURE") == 0){
  358.         return o;
  359.     }
  360.     if(strcmp(a, "LAMBDA") == 0){
  361.         return cons(mka("CLOSURE"), cons(env, cdr(o)));
  362.     }
  363.     o = cdr(o);
  364.  
  365.     if(strcmp(a, "CONS") == 0){
  366.         o = evalargs(o, env);
  367.         return cons(car(o), car(cdr(o)));
  368.     }
  369.     if(strcmp(a, "CAR") == 0)
  370.         return car(eval(car(o), env));
  371.     if(strcmp(a, "CDR") == 0)
  372.         return cdr(eval(car(o), env));
  373.     if(strcmp(a, "IF") == 0){
  374.         /* (IF (cond expr) expr) */
  375.         if(eval(car(car(o)), env) != nil)
  376.             return eval(car(cdr(car(o))), env);
  377.         else
  378.             return eval(car(cdr(o)), env);
  379.     }
  380.     if(strcmp(a, "LET") == 0){
  381.         /* (let ((x 6) (n 3)) (cond etc...)) */
  382.         for(vars = car(o); vars != nil; vars = cdr(vars))
  383.             env = cons(cons(car(car(vars)), cons(eval(car(cdr(car(vars))), env), nil)), env);
  384.         //prin1(env);
  385.         //prin1(car(cdr(o)));
  386.         return eval(car(cdr(o)), env);
  387.     }
  388.     if(strcmp(a, "QUOTE") == 0)
  389.         return car(o);
  390.  
  391.     printf("eval reached bottom oops\n");
  392.     return nil;
  393. }
  394.  
  395. void
  396. main(void)
  397. {
  398.     O *o;
  399.  
  400.     printf("Welcome to Lisp\n");
  401.     for(;;){
  402.         printf("> ");
  403.         o = eval(r(), nil);
  404.         prin1(o);
  405.         printf("\n");
  406.         if(o == nil) return;
  407.     }
  408. }
Advertisement
Add Comment
Please, Sign In to add comment