PageRenderTime 74ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/a++/appc/arsclib.c

https://github.com/pib/500pl
C | 553 lines | 399 code | 95 blank | 59 comment | 38 complexity | 37b03d55d1689b590116679b759fbc8c MD5 | raw file
  1. /***********************************************************************
  2. arsc.c - description
  3. ----------------------
  4. begin : Wed Apr 17 2001
  5. update : Sa Aug 06 2004
  6. copyright : (C) 2001 by Georg P. Loczewski
  7. email : gpl@lambda-bound.com
  8. **********************************************************************/
  9. /***********************************************************************
  10. * *
  11. * This program is free software; you can redistribute it and/or modify *
  12. * it under the terms of the GNU General Public License as published by *
  13. * the Free Software Foundation; either version 2 of the License, or *
  14. * (at your option) any later version. *
  15. * *
  16. ***********************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <setjmp.h>
  20. #include <malloc.h>
  21. #include "gc.h"
  22. #include <string.h>
  23. #include "arsc.h"
  24. extern jmp_buf _EXH;
  25. EXP *currentExp;
  26. ENV *globalEnv;
  27. EXP *trueSym;
  28. char *nameTable[MAX_NAMES];
  29. NAME numNames;
  30. NAME setName;
  31. NAME eof;
  32. NAME lambda;
  33. VALUE *setVal;
  34. VALUE *falseValue, *trueValue;
  35. int false;
  36. int true;
  37. /*****************************************************************
  38. * ADT CONSTRUCTORS *
  39. *****************************************************************/
  40. /* newVAL - make a value (evaluated expression) */
  41. VALUE *
  42. newVAL (VTYPE t)
  43. {
  44. VALUE *val;
  45. val = (VALUE *) GC_malloc (sizeof (VALUE));
  46. val->type = t;
  47. return val;
  48. }
  49. /* newLISTV - represent a value list as a value */
  50. VALUE *
  51. newLISTV (VLIST *vl)
  52. {
  53. VALUE *val;
  54. if (vl) {
  55. val = (VALUE *) GC_malloc (sizeof (VALUE));
  56. val->type = LISTV;
  57. val->val.lv.car = vl->head;
  58. val->val.lv.cdr = newLISTV(vl->tail);
  59. return val;
  60. }
  61. else {
  62. return NULL;
  63. }
  64. }
  65. /* newPRIMV - make a primitive value */
  66. VALUE *
  67. newPRIMV (PRIM prim)
  68. {
  69. VALUE *result;
  70. result = (VALUE *) GC_malloc (sizeof (VALUE));
  71. result->type = PRIMV;
  72. result->val.prim = prim;
  73. return result;
  74. }
  75. /* newSTRV- make a string value */
  76. VALUE *
  77. newSTRV(NAME nm)
  78. {
  79. VALUE *result;
  80. result = (VALUE *) GC_malloc (sizeof (VALUE));
  81. result->type = STRV;
  82. result->val.str = nm;
  83. return result;
  84. }
  85. /* newSYMV- make a symbol value */
  86. VALUE *
  87. newSYMV(NAME nm)
  88. {
  89. VALUE *result;
  90. result = (VALUE *) GC_malloc (sizeof (VALUE));
  91. result->type = SYMV;
  92. result->val.sym = nm;
  93. return result;
  94. }
  95. /* newINTV- make an integer value */
  96. VALUE *
  97. newINTV (int i)
  98. {
  99. VALUE *result;
  100. result = (VALUE *) GC_malloc (sizeof (VALUE));
  101. result->type = INTV;
  102. result->val.ival = i;
  103. return result;
  104. }
  105. /* newACLV- make an ars-closure */
  106. VALUE *
  107. newACLV (EXP * fun, ENV * env)
  108. {
  109. VALUE *result;
  110. result = (VALUE *) GC_malloc (sizeof (VALUE));
  111. result->type = ACLV;
  112. result->val.acl.fun = fun;
  113. result->val.acl.env = env;
  114. return result;
  115. }
  116. /* newCLAMV- make a c-lambda abstraction */
  117. VALUE *
  118. newCLAMV (NLIST * vars, LFUN lfun, ENV *env)
  119. {
  120. VALUE *cl;
  121. cl = (VALUE *) GC_malloc (sizeof (VALUE));
  122. cl->type = CLAMV;
  123. cl->val.clam.vars = vars;
  124. cl->val.clam.lfun = lfun;
  125. cl->val.clam.env = env;
  126. return cl;
  127. }
  128. /* ncons - make a list of names */
  129. NLIST *
  130. ncons (NAME nm, NLIST * nl)
  131. {
  132. NLIST *newnl;
  133. newnl = (NLIST *) GC_malloc (sizeof (NLIST));
  134. newnl->head = nm;
  135. newnl->tail = nl;
  136. return newnl;
  137. }
  138. /* vcons - make a list of values */
  139. VLIST *
  140. vcons (VALUE * val, VLIST * vl)
  141. {
  142. VLIST *newvl;
  143. newvl = (VLIST *) GC_malloc (sizeof (VLIST));
  144. newvl->head = val;
  145. newvl->tail = vl;
  146. return newvl;
  147. }
  148. /* cons - make a list of values */
  149. VALUE *
  150. cons (VALUE * hd, VALUE * tl)
  151. {
  152. VALUE *newvl;
  153. newvl = (VALUE *) GC_malloc (sizeof (VALUE));
  154. newvl->type = LISTV;
  155. newvl->val.lv.car = hd;
  156. newvl->val.lv.cdr = tl;
  157. return newvl;
  158. }
  159. /* newENV - make an environment */
  160. ENV *
  161. newENV (NLIST * nl, VLIST * vl, ENV * env)
  162. {
  163. ENV *newenv;
  164. newenv = (ENV *) GC_malloc (sizeof (ENV));
  165. newenv->vars = nl;
  166. newenv->values = vl;
  167. newenv->next = env;
  168. return newenv;
  169. }
  170. /*****************************************************************
  171. * NAMES OF VARIABLES *
  172. *****************************************************************/
  173. /* initNames - place all pre-defined names into nameTable */
  174. void
  175. initNames ()
  176. {
  177. long i = 1;
  178. nameTable[i - 1] = "define";
  179. i++;
  180. nameTable[i - 1] = "incr";
  181. i++;
  182. nameTable[i - 1] = "+";
  183. i++;
  184. nameTable[i - 1] = "-";
  185. i++;
  186. nameTable[i - 1] = "*";
  187. i++;
  188. nameTable[i - 1] = "/";
  189. i++;
  190. nameTable[i - 1] = "print";
  191. i++;
  192. nameTable[i - 1] = "load";
  193. i++;
  194. nameTable[i - 1] = "equal";
  195. i++;
  196. nameTable[i - 1] = ">=";
  197. i++;
  198. nameTable[i - 1] = "<";
  199. i++;
  200. nameTable[i - 1] = "quit";
  201. i++;
  202. nameTable[i - 1] = "false";
  203. i++;
  204. nameTable[i - 1] = "true";
  205. numNames = i;
  206. }
  207. /* defName - insert new name into nameTable */
  208. NAME
  209. defName (char *nm)
  210. {
  211. long i = 1;
  212. int found = false;
  213. while (i <= numNames && !found) {
  214. if (!strcmp (nm, nameTable[i - 1]))
  215. found = true;
  216. else
  217. i++;
  218. }
  219. if (found)
  220. return i;
  221. if (i > MAX_NAMES) {
  222. printf ("No more room for names\n");
  223. longjmp (_EXH, 1);
  224. }
  225. numNames = i;
  226. nameTable[i - 1] = nm;
  227. return i;
  228. }
  229. /* prName - print name nm */
  230. void
  231. prName (NAME nm)
  232. {
  233. printf ("%s", nameTable[nm - 1]);
  234. }
  235. /* prString - print string nm (strings are handled like symbols ) */
  236. void
  237. prString (NAME nm)
  238. {
  239. printf ("%s", nameTable[nm - 1]);
  240. }
  241. /* lengthNL - return length of NLIST nl */
  242. long
  243. lengthNL (NLIST * nl)
  244. {
  245. long i = 0;
  246. while (nl != NULL) {
  247. i++;
  248. nl = nl->tail;
  249. }
  250. return i;
  251. }
  252. /* prNL - print list of names */
  253. void
  254. prNL (NLIST * nl)
  255. {
  256. long i = 0;
  257. putchar ('(');
  258. while (nl != NULL) {
  259. i++;
  260. prName (nl->head);
  261. nl = nl->tail;
  262. if (nl != NULL) {
  263. putchar (' ');
  264. }
  265. }
  266. printf (")\n");
  267. }
  268. /*****************************************************************
  269. * VARIABLES AND ENVIRONMENTS *
  270. *****************************************************************/
  271. /* emptyEnv - return an environment with no bindings */
  272. ENV *
  273. emptyEnv ()
  274. {
  275. return (newENV (NULL, NULL, NULL));
  276. }
  277. /* defVar - bind variable nm to value val in environment env */
  278. void
  279. defVar (NAME nm, VALUE * val, ENV * env)
  280. {
  281. env->vars = ncons (nm, env->vars);
  282. env->values = vcons (val, env->values);
  283. }
  284. /* setVar - set variable nm to value val in env */
  285. void
  286. setVar (NAME nm, VALUE * val, ENV * env)
  287. {
  288. VLIST *vl;
  289. vl = bindingInEnv (nm, env);
  290. if (vl) {
  291. vl->head = val;
  292. }
  293. else {
  294. printf("variable not defined: ");
  295. prName(nm);
  296. printf("\n");
  297. }
  298. }
  299. /* getVar - return VAL bound to nm in env */
  300. VALUE *
  301. getVar (NAME nm, ENV * env)
  302. {
  303. VLIST *vl;
  304. vl = bindingInEnv (nm, env);
  305. if (vl)
  306. return (vl->head);
  307. else
  308. return falseValue;
  309. }
  310. /* extendEnv - extend environment env by binding vars to vals */
  311. ENV *
  312. extendEnv (ENV * env, NLIST * vars, VLIST * vals)
  313. {
  314. return (newENV (vars, vals, env));
  315. }
  316. /* bindingInFrame - look up nm in one frame */
  317. VLIST *
  318. bindingInFrame (NLIST * nl, VLIST * vl, NAME nm)
  319. {
  320. int found = false;
  321. while (nl != NULL && !found) {
  322. if (nl->head == nm)
  323. found = true;
  324. else {
  325. nl = nl->tail;
  326. vl = vl->tail;
  327. }
  328. }
  329. return vl;
  330. }
  331. /* bindingInEnv - look up nm in env */
  332. VLIST *
  333. bindingInEnv (NAME nm, ENV * env)
  334. {
  335. VLIST *vl;
  336. do {
  337. vl = bindingInFrame (env->vars, env->values, nm);
  338. env = env->next;
  339. } while (vl == NULL && env != NULL);
  340. return vl;
  341. }
  342. /* isBound - check if nm is bound in env */
  343. int
  344. isBound (NAME nm, ENV * env)
  345. {
  346. return (bindingInEnv (nm, env) != NULL);
  347. }
  348. /* initGlobalEnv - initialize global environment */
  349. void
  350. initGlobalEnv ()
  351. {
  352. PRIM op;
  353. false = 0;
  354. true = 1;
  355. falseValue = newVAL (SYMV);
  356. trueValue = newVAL (SYMV);
  357. falseValue->val.sym = defName("false");
  358. trueValue->val.sym = defName("true");
  359. globalEnv = emptyEnv ();
  360. setVal->val.ival = 0;
  361. defVar (setName, setVal, globalEnv);
  362. eof = defName (strdup ("*eof*"));
  363. lambda = defName (strdup ("lambda"));
  364. }
  365. /*****************************************************************
  366. * EVALUATION AND VALUES *
  367. *****************************************************************/
  368. /* apply - apply c-closure to arguments */
  369. VALUE *
  370. apply (VALUE * cl, VLIST * args)
  371. {
  372. LFUN lfun;
  373. NLIST *names;
  374. ENV *savedenv, *newenv;
  375. savedenv = cl->val.clam.env;
  376. names = cl->val.clam.vars;
  377. lfun = cl->val.clam.lfun;
  378. if (lengthNL (names) != lengthVL (args)) {
  379. printf ("Wrong number of arguments to closure\n");
  380. printf ("names\n");
  381. prNL (names);
  382. printf ("arguments\n");
  383. prVL (args);
  384. longjmp (_EXH, 1);
  385. }
  386. newenv = extendEnv (savedenv, names, args);
  387. return (lfun(newenv));
  388. }
  389. /* prValue - print value val */
  390. void
  391. prValue (VALUE * val)
  392. {
  393. int i;
  394. if (val != NULL) {
  395. switch (val->type) {
  396. case INTV:
  397. printf ("%ld", val->val.ival);
  398. break;
  399. case SYMV:
  400. prString (val->val.sym);
  401. break;
  402. case STRV:
  403. prString (val->val.str);
  404. break;
  405. case LISTV:
  406. i = 0;
  407. putchar ('(');
  408. while (val != NULL) {
  409. i++;
  410. prValue (val->val.lv.car);
  411. putchar (' ');
  412. val = val->val.lv.cdr;
  413. }
  414. printf (")\n");
  415. break;
  416. case PRIMV:
  417. printf ("<primitive: ");
  418. prName ((int) val->val.prim + 1);
  419. putchar ('>');
  420. break;
  421. case ACLV:
  422. printf ("lambda");
  423. prNL(val->val.acl.fun->exp.abs.vars);
  424. break;
  425. case CLAMV:
  426. printf ("<c-lambda-abstraction>");
  427. break;
  428. case THUNKV:
  429. printf ("...");
  430. break;
  431. }
  432. }
  433. }
  434. /* lengthVL - return length of VLIST vl */
  435. long
  436. lengthVL (VLIST * vl)
  437. {
  438. long i = 0;
  439. while (vl != NULL) {
  440. i++;
  441. vl = vl->tail;
  442. }
  443. return i;
  444. }
  445. /* prVL - print list of values */
  446. void
  447. prVL (VLIST * vl)
  448. {
  449. long i = 0;
  450. putchar ('(');
  451. while (vl != NULL) {
  452. i++;
  453. prValue (vl->head);
  454. putchar (' ');
  455. vl = vl->tail;
  456. }
  457. printf (")\n");
  458. }