Guest User

thp.c

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