PageRenderTime 62ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/a++/appc/arsc.c

https://github.com/pib/500pl
C | 1010 lines | 794 code | 135 blank | 81 comment | 138 complexity | 5793197592e74bc3cba4f053f50ee359 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. /* newVXP - make a value expression */
  41. EXP *
  42. newVXP (VALUE * val)
  43. {
  44. EXP *e;
  45. e = (EXP *) GC_malloc (sizeof (EXP));
  46. e->etype = VXP;
  47. e->exp.val = val;
  48. return e;
  49. }
  50. /* newRXP - make a variable expression (reference) */
  51. EXP *
  52. newRXP (NAME nm)
  53. {
  54. EXP *e;
  55. e = (EXP *) GC_malloc (sizeof (EXP));
  56. e->etype = RXP;
  57. e->exp.ref = nm;
  58. return e;
  59. }
  60. /* newSXP - make an application expression (synthesis) */
  61. EXP *
  62. newSXP (EXP * op, ELIST * el)
  63. {
  64. EXP *e;
  65. e = (EXP *) GC_malloc (sizeof (EXP));
  66. e->etype = SXP;
  67. e->exp.syn.op = op;
  68. e->exp.syn.args = el;
  69. return e;
  70. }
  71. /* newAXP - make a lambda expression (abstraction) */
  72. EXP *
  73. newAXP (NLIST * formals, ELIST * body)
  74. {
  75. EXP *e;
  76. e = (EXP *) GC_malloc (sizeof (EXP));
  77. e->etype = AXP;
  78. e->exp.abs.vars = formals;
  79. e->exp.abs.body = body;
  80. return e;
  81. }
  82. /* newVAL - make a value (evaluated expression) */
  83. VALUE *
  84. newVAL (VTYPE t)
  85. {
  86. VALUE *val;
  87. val = (VALUE *) GC_malloc (sizeof (VALUE));
  88. val->type = t;
  89. return val;
  90. }
  91. /* newLISTV - represent a value list as a value */
  92. VALUE *
  93. newLISTV (VLIST *vl)
  94. {
  95. VALUE *val;
  96. if (vl) {
  97. val = (VALUE *) GC_malloc (sizeof (VALUE));
  98. val->type = LISTV;
  99. val->val.lv.car = vl->head;
  100. val->val.lv.cdr = newLISTV(vl->tail);
  101. return val;
  102. }
  103. else {
  104. return NULL;
  105. }
  106. }
  107. /* newPRIMV - make a primitive value */
  108. VALUE *
  109. newPRIMV (PRIM prim)
  110. {
  111. VALUE *result;
  112. result = (VALUE *) GC_malloc (sizeof (VALUE));
  113. result->type = PRIMV;
  114. result->val.prim = prim;
  115. return result;
  116. }
  117. /* newSTRV- make a string value */
  118. VALUE *
  119. newSTRV(NAME nm)
  120. {
  121. VALUE *result;
  122. result = (VALUE *) GC_malloc (sizeof (VALUE));
  123. result->type = STRV;
  124. result->val.str = nm;
  125. return result;
  126. }
  127. /* newSYMV- make a symbol value */
  128. VALUE *
  129. newSYMV(NAME nm)
  130. {
  131. VALUE *result;
  132. result = (VALUE *) GC_malloc (sizeof (VALUE));
  133. result->type = SYMV;
  134. result->val.sym = nm;
  135. return result;
  136. }
  137. /* newINTV- make an integer value */
  138. VALUE *
  139. newINTV (int i)
  140. {
  141. VALUE *result;
  142. result = (VALUE *) GC_malloc (sizeof (VALUE));
  143. result->type = INTV;
  144. result->val.ival = i;
  145. return result;
  146. }
  147. /* newACLV- make an ars-closure */
  148. VALUE *
  149. newACLV (EXP * fun, ENV * env)
  150. {
  151. VALUE *result;
  152. result = (VALUE *) GC_malloc (sizeof (VALUE));
  153. result->type = ACLV;
  154. result->val.acl.fun = fun;
  155. result->val.acl.env = env;
  156. return result;
  157. }
  158. /* newCLAMV- make a c-lambda abstraction */
  159. VALUE *
  160. newCLAMV (NLIST * vars, LFUN lfun, ENV *env)
  161. {
  162. VALUE *cl;
  163. cl = (VALUE *) GC_malloc (sizeof (VALUE));
  164. cl->type = CLAMV;
  165. cl->val.clam.vars = vars;
  166. cl->val.clam.lfun = lfun;
  167. cl->val.clam.env = env;
  168. return cl;
  169. }
  170. /* newTHUNKV - make a frozen expression (delayed evaluation) */
  171. VALUE *
  172. newTHUNKV (EXP * e, ENV * env)
  173. {
  174. VALUE *result;
  175. result = (VALUE *) GC_malloc (sizeof (VALUE));
  176. result->type = THUNKV;
  177. result->val.thunk.body = e;
  178. result->val.thunk.env = env;
  179. return result;
  180. }
  181. /* econs - make a list of expressions */
  182. ELIST *
  183. econs (EXP * e, ELIST * el)
  184. {
  185. ELIST *newel;
  186. newel = (ELIST *) GC_malloc (sizeof (ELIST));
  187. newel->head = e;
  188. newel->tail = el;
  189. return newel;
  190. }
  191. /* ncons - make a list of names */
  192. NLIST *
  193. ncons (NAME nm, NLIST * nl)
  194. {
  195. NLIST *newnl;
  196. newnl = (NLIST *) GC_malloc (sizeof (NLIST));
  197. newnl->head = nm;
  198. newnl->tail = nl;
  199. return newnl;
  200. }
  201. /* vcons - make a list of values */
  202. VLIST *
  203. vcons (VALUE * val, VLIST * vl)
  204. {
  205. VLIST *newvl;
  206. newvl = (VLIST *) GC_malloc (sizeof (VLIST));
  207. newvl->head = val;
  208. newvl->tail = vl;
  209. return newvl;
  210. }
  211. /* cons - make a list of values */
  212. VALUE *
  213. cons (VALUE * hd, VALUE * tl)
  214. {
  215. VALUE *newvl;
  216. newvl = (VALUE *) GC_malloc (sizeof (VALUE));
  217. newvl->type = LISTV;
  218. newvl->val.lv.car = hd;
  219. newvl->val.lv.cdr = tl;
  220. return newvl;
  221. }
  222. /* newENV - make an environment */
  223. ENV *
  224. newENV (NLIST * nl, VLIST * vl, ENV * env)
  225. {
  226. ENV *newenv;
  227. newenv = (ENV *) GC_malloc (sizeof (ENV));
  228. newenv->vars = nl;
  229. newenv->values = vl;
  230. newenv->next = env;
  231. return newenv;
  232. }
  233. /*****************************************************************
  234. * NAMES OF VARIABLES *
  235. *****************************************************************/
  236. /* initNames - place all pre-defined names into nameTable */
  237. void
  238. initNames ()
  239. {
  240. long i = 1;
  241. nameTable[i - 1] = "define";
  242. i++;
  243. nameTable[i - 1] = "incr";
  244. i++;
  245. nameTable[i - 1] = "+";
  246. i++;
  247. nameTable[i - 1] = "-";
  248. i++;
  249. nameTable[i - 1] = "*";
  250. i++;
  251. nameTable[i - 1] = "/";
  252. i++;
  253. nameTable[i - 1] = "print";
  254. i++;
  255. nameTable[i - 1] = "load";
  256. i++;
  257. nameTable[i - 1] = "equal";
  258. i++;
  259. nameTable[i - 1] = ">=";
  260. i++;
  261. nameTable[i - 1] = "<";
  262. i++;
  263. nameTable[i - 1] = "quit";
  264. i++;
  265. nameTable[i - 1] = "false";
  266. i++;
  267. nameTable[i - 1] = "true";
  268. numNames = i;
  269. }
  270. /* defName - insert new name into nameTable */
  271. NAME
  272. defName (char *nm)
  273. {
  274. long i = 1;
  275. int found = false;
  276. while (i <= numNames && !found) {
  277. if (!strcmp (nm, nameTable[i - 1]))
  278. found = true;
  279. else
  280. i++;
  281. }
  282. if (found)
  283. return i;
  284. if (i > MAX_NAMES) {
  285. printf ("No more room for names\n");
  286. longjmp (_EXH, 1);
  287. }
  288. numNames = i;
  289. nameTable[i - 1] = nm;
  290. return i;
  291. }
  292. /* prName - print name nm */
  293. void
  294. prName (NAME nm)
  295. {
  296. printf ("%s", nameTable[nm - 1]);
  297. }
  298. /* prString - print string nm (strings are handled like symbols ) */
  299. void
  300. prString (NAME nm)
  301. {
  302. printf ("%s", nameTable[nm - 1]);
  303. }
  304. /* lengthNL - return length of NLIST nl */
  305. long
  306. lengthNL (NLIST * nl)
  307. {
  308. long i = 0;
  309. while (nl != NULL) {
  310. i++;
  311. nl = nl->tail;
  312. }
  313. return i;
  314. }
  315. /* prNL - print list of names */
  316. void
  317. prNL (NLIST * nl)
  318. {
  319. long i = 0;
  320. putchar ('(');
  321. while (nl != NULL) {
  322. i++;
  323. prName (nl->head);
  324. nl = nl->tail;
  325. if (nl != NULL) {
  326. putchar (' ');
  327. }
  328. }
  329. printf (")\n");
  330. }
  331. /*****************************************************************
  332. * VARIABLES AND ENVIRONMENTS *
  333. *****************************************************************/
  334. /* emptyEnv - return an environment with no bindings */
  335. ENV *
  336. emptyEnv ()
  337. {
  338. return (newENV (NULL, NULL, NULL));
  339. }
  340. /* defVar - bind variable nm to value val in environment env */
  341. void
  342. defVar (NAME nm, VALUE * val, ENV * env)
  343. {
  344. env->vars = ncons (nm, env->vars);
  345. env->values = vcons (val, env->values);
  346. }
  347. /* setVar - set variable nm to value val in env */
  348. void
  349. setVar (NAME nm, VALUE * val, ENV * env)
  350. {
  351. VLIST *vl;
  352. vl = bindingInEnv (nm, env);
  353. if (vl) {
  354. vl->head = val;
  355. }
  356. else {
  357. printf("variable not defined: ");
  358. prName(nm);
  359. printf("\n");
  360. }
  361. }
  362. /* getVar - return VAL bound to nm in env */
  363. VALUE *
  364. getVar (NAME nm, ENV * env)
  365. {
  366. VLIST *vl;
  367. vl = bindingInEnv (nm, env);
  368. if (vl)
  369. return (vl->head);
  370. else
  371. return falseValue;
  372. }
  373. /* extendEnv - extend environment env by binding vars to vals */
  374. ENV *
  375. extendEnv (ENV * env, NLIST * vars, VLIST * vals)
  376. {
  377. return (newENV (vars, vals, env));
  378. }
  379. /* bindingInFrame - look up nm in one frame */
  380. VLIST *
  381. bindingInFrame (NLIST * nl, VLIST * vl, NAME nm)
  382. {
  383. int found = false;
  384. while (nl != NULL && !found) {
  385. if (nl->head == nm)
  386. found = true;
  387. else {
  388. nl = nl->tail;
  389. vl = vl->tail;
  390. }
  391. }
  392. return vl;
  393. }
  394. /* bindingInEnv - look up nm in env */
  395. VLIST *
  396. bindingInEnv (NAME nm, ENV * env)
  397. {
  398. VLIST *vl;
  399. do {
  400. vl = bindingInFrame (env->vars, env->values, nm);
  401. env = env->next;
  402. } while (vl == NULL && env != NULL);
  403. return vl;
  404. }
  405. /* isBound - check if nm is bound in env */
  406. int
  407. isBound (NAME nm, ENV * env)
  408. {
  409. return (bindingInEnv (nm, env) != NULL);
  410. }
  411. /* initGlobalEnv - initialize global environment */
  412. void
  413. initGlobalEnv ()
  414. {
  415. PRIM op;
  416. false = 0;
  417. true = 1;
  418. falseValue = newVAL (SYMV);
  419. trueValue = newVAL (SYMV);
  420. falseValue->val.sym = defName("false");
  421. trueValue->val.sym = defName("true");
  422. trueSym = newRXP (trueValue->val.sym);
  423. globalEnv = emptyEnv ();
  424. for (op = PRIMDEF;
  425. (long) op <= (long) PRIMQUIT; op = (PRIM) ((long) op + 1)) {
  426. defVar ((int) op + 1, newPRIMV (op), globalEnv);
  427. }
  428. setName = defName (strdup ("vmzero"));
  429. setVal = newVAL(INTV);
  430. setVal->val.ival = 0;
  431. defVar (setName, setVal, globalEnv);
  432. setName = defName (strdup ("vmtrue"));
  433. setVal = trueValue;
  434. defVar (setName, setVal, globalEnv);
  435. setName = defName (strdup ("vmfalse"));
  436. setVal = falseValue;
  437. defVar (setName, setVal, globalEnv);
  438. eof = defName (strdup ("*eof*"));
  439. lambda = defName (strdup ("lambda"));
  440. }
  441. /*****************************************************************
  442. * EVALUATION AND VALUES *
  443. *****************************************************************/
  444. /* eval - evaluate expression e in local environment env */
  445. VALUE *
  446. eval (EXP * e, ENV * env, EXP * lazy)
  447. {
  448. VALUE *result, *op;
  449. PRIM primname;
  450. switch (e->etype) {
  451. case VXP:
  452. result = e->exp.val;
  453. break;
  454. case RXP:
  455. if (isBound (e->exp.ref, env))
  456. result = getVar(e->exp.ref, env);
  457. else {
  458. printf ("Undefined variable: ");
  459. prName (e->exp.ref);
  460. putchar ('\n');
  461. longjmp (_EXH, 1);
  462. }
  463. result = evalThunk (result);
  464. break;
  465. case SXP:
  466. op = evalThunk (eval (e->exp.syn.op, env, lazy));
  467. if (op->type == PRIMV) {
  468. primname = op->val.prim;
  469. if (primname == PRIMDEF)
  470. result = applySpecialForm (PRIMDEF, e->exp.syn.args, env);
  471. else
  472. result = applyPrimitive (primname,
  473. evalList (e->exp.syn.args, env, lazy));
  474. }
  475. else
  476. result = applyARSClosure (op,
  477. evalList (e->exp.syn.args, env, lazy),
  478. lazy);
  479. break;
  480. case AXP:
  481. result = newACLV(e, env);
  482. break;
  483. }
  484. return result;
  485. }
  486. /* evalThunk - enforce evaluation of frozen expression */
  487. /* memoizing version would be faster than standard version but not as */
  488. /* flexible and is not used here to provide maximum flexibility for */
  489. /* ARS ( to allow implementing special forms as normal functions */
  490. VALUE *
  491. evalThunk (VALUE * val)
  492. {
  493. if (val->type == THUNKV)
  494. return (evalThunk (eval (val->val.acl.fun,
  495. val->val.acl.env, trueSym)));
  496. else
  497. return val;
  498. }
  499. /* applyPrimitive - apply PRIM op to arguments in VLIST vl */
  500. VALUE *
  501. applyPrimitive (PRIM op, VLIST * vl)
  502. {
  503. VALUE *result, *v1, *v2;
  504. int nargs;
  505. nargs = lengthVL (vl);
  506. switch (nargs) {
  507. case 0:
  508. if (op == PRIMQUIT) {
  509. longjmp (_EXH, 2);
  510. }
  511. else {
  512. printf ("Illegal operation: ");
  513. prName ((int) op + 1);
  514. putchar ('\n');
  515. longjmp (_EXH, 1);
  516. }
  517. break;
  518. case 1:
  519. v1 = evalThunk (vl->head); /* 1st actual */
  520. switch (op) {
  521. case PRIMINCR:
  522. if (v1->type == INTV) {
  523. result = newVAL (INTV);
  524. result->val.ival = v1->val.ival + 1;
  525. return result;
  526. }
  527. else {
  528. printf ("Non-arithmetic arguments to ");
  529. prName ((int) op + 1);
  530. putchar ('\n');
  531. prValue (v1);
  532. longjmp (_EXH, 1);
  533. }
  534. break;
  535. case PRIMPRINT:
  536. printf("-->");
  537. prValue (v1);
  538. putchar ('\n');
  539. result = newVAL (SYMV);;
  540. result->val.sym = defName("void\n");
  541. break;
  542. case PRIMLOAD:
  543. prValue (v1);
  544. putchar ('\n');
  545. result = load (v1);
  546. break;
  547. default:
  548. printf ("undefined primitive operation\n ");
  549. prName ((int) op + 1);
  550. putchar ('\n');
  551. longjmp (_EXH, 2);
  552. }
  553. break;
  554. case 2:
  555. v1 = evalThunk (vl->head); /* 1st actual */
  556. v2 = evalThunk (vl->tail->head); /* 2nd actual */
  557. switch (op) {
  558. case PRIMADD:
  559. if ((v1->type == INTV) && (v2->type == INTV)) {
  560. result = newVAL (INTV);
  561. result->val.ival = v1->val.ival + v2->val.ival;
  562. }
  563. else {
  564. printf ("PRIMADD:\n ");
  565. printf ("Integer argument expected!\n ");
  566. longjmp (_EXH, 2);
  567. }
  568. break;
  569. case PRIMSUB:
  570. if ((v1->type == INTV) && (v2->type == INTV)) {
  571. result = newINTV (v1->val.ival - v2->val.ival);
  572. }
  573. else {
  574. printf ("PRIMSUB:\n ");
  575. printf ("Integer argument expected!\n ");
  576. longjmp (_EXH, 2);
  577. }
  578. break;
  579. case PRIMMLT:
  580. if ((v1->type == INTV) && (v2->type == INTV)) {
  581. result = newINTV (v1->val.ival * v2->val.ival);
  582. }
  583. else {
  584. printf ("PRIMMLT:\n ");
  585. printf ("Integer argument expected!\n ");
  586. longjmp (_EXH, 2);
  587. }
  588. break;
  589. case PRIMDIV:
  590. if ((v1->type == INTV) && (v2->type == INTV)) {
  591. result = newINTV (v1->val.ival / v2->val.ival);
  592. }
  593. else {
  594. printf ("Integer argument expected!\n ");
  595. longjmp (_EXH, 2);
  596. }
  597. break;
  598. case PRIMGE:
  599. if (v1->type != v2->type) {
  600. result = getVar(defName("false"), globalEnv);
  601. }
  602. else if ((v1->type == INTV) &&
  603. (v1->val.ival >= v2->val.ival)) {
  604. result = getVar(defName("true"), globalEnv);
  605. }
  606. else {
  607. result = getVar(defName("false"), globalEnv);
  608. }
  609. break;
  610. case PRIMLT:
  611. if (v1->type != v2->type) {
  612. result = getVar(defName("false"), globalEnv);
  613. }
  614. else if ((v1->type == INTV) &&
  615. (v1->val.ival < v2->val.ival)) {
  616. result = getVar(defName("true"), globalEnv);
  617. }
  618. else {
  619. result = getVar(defName("false"), globalEnv);
  620. }
  621. break;
  622. case PRIMEQUAL:
  623. if (v1 == v2) {
  624. result = getVar(defName("true"), globalEnv);
  625. }
  626. else if (v1->type != v2->type) {
  627. result = getVar(defName("false"), globalEnv);
  628. }
  629. else if ((v1->type == INTV) &&
  630. (v1->val.ival == v2->val.ival)) {
  631. result = getVar(defName("true"), globalEnv);
  632. }
  633. else if (v1->type == SYMV) {
  634. if (v1->val.sym == v2->val.sym) {
  635. result = getVar(defName("true"), globalEnv);
  636. }
  637. else {
  638. result = getVar(defName("false"), globalEnv);
  639. }
  640. }
  641. else if (v1->type == STRV) {
  642. if (v1->val.str == v2->val.str) {
  643. result = getVar(defName("true"), globalEnv);
  644. }
  645. else {
  646. result = getVar(defName("false"), globalEnv);
  647. }
  648. }
  649. else {
  650. result = getVar(defName("false"), globalEnv);
  651. }
  652. break;
  653. default:
  654. printf ("undefined primitive operation\n ");
  655. prName ((int) op + 1);
  656. putchar ('\n');
  657. longjmp (_EXH, 2);
  658. }
  659. break;
  660. default:
  661. printf ("Wrong number of arguments to ");
  662. prName ((int) op + 1);
  663. putchar ('\n');
  664. longjmp (_EXH, 1);
  665. }
  666. return result;
  667. }
  668. /* lazyp - checks if lazy evaluation is to be applied */
  669. int
  670. lazyp (EXP * e1, EXP * e2)
  671. {
  672. if (e1->etype == RXP && e2->etype == RXP) {
  673. if (e1->exp.ref == e2->exp.ref)
  674. return false;
  675. else
  676. return true;
  677. }
  678. else
  679. return true;
  680. }
  681. /* evalList - evaluate each expression in el */
  682. VLIST *
  683. evalList (ELIST * el, ENV * env, EXP * lazy)
  684. {
  685. VALUE *h;
  686. VLIST *t;
  687. if (el == NULL)
  688. return NULL;
  689. else {
  690. if (lazyp (el->head, lazy))
  691. h = newTHUNKV (el->head, env);
  692. else
  693. h = evalThunk (eval (el->head, env, lazy));
  694. t = evalList (el->tail, env, lazy);
  695. return (vcons (h, t));
  696. }
  697. }
  698. /* evalSequence - evaluate a sequence of expressions */
  699. VALUE *
  700. evalSequence (ELIST * el, ENV * newenv, EXP * lazy)
  701. {
  702. while (el->tail != NULL) {
  703. evalThunk (eval (el->head, newenv, lazy));
  704. el = el->tail;
  705. }
  706. return (evalThunk (eval (el->head, newenv, lazy)));
  707. }
  708. /* applyARSClosure - apply closure to arguments */
  709. VALUE *
  710. applyARSClosure (VALUE * op, VLIST * args, EXP * lazy)
  711. {
  712. EXP *fun;
  713. ELIST *body;
  714. NLIST *names;
  715. ENV *savedenv, *newenv;
  716. fun = op->val.acl.fun;
  717. savedenv = op->val.acl.env;
  718. names = fun->exp.abs.vars;
  719. body = fun->exp.abs.body;
  720. if (lengthNL (names) != lengthVL (args)) {
  721. printf ("Wrong number of arguments to closure\n");
  722. printf ("names\n");
  723. prNL (names);
  724. printf ("arguments\n");
  725. prVL (args);
  726. longjmp (_EXH, 1);
  727. }
  728. newenv = extendEnv (savedenv, names, args);
  729. return (evalSequence (body, newenv, lazy));
  730. }
  731. /* applySpecialForm - evaluate special form */
  732. VALUE *
  733. applySpecialForm (PRIM op, ELIST * args, ENV * env)
  734. {
  735. VALUE *result;
  736. if (op == PRIMDEF) {
  737. result = evalThunk (eval (args->tail->head, env, args->head));
  738. if (isBound (args->head->exp.ref, env)) {
  739. setVar (args->head->exp.ref, result, env);
  740. }
  741. else {
  742. defVar (args->head->exp.ref, result, env);
  743. }
  744. }
  745. else {
  746. printf ("undefined control operation!\n");
  747. longjmp (_EXH, 2);
  748. }
  749. return result;
  750. }
  751. /* apply - apply c-closure to arguments */
  752. VALUE *
  753. apply (VALUE * cl, VLIST * args)
  754. {
  755. LFUN lfun;
  756. NLIST *names;
  757. ENV *savedenv, *newenv;
  758. savedenv = cl->val.clam.env;
  759. names = cl->val.clam.vars;
  760. lfun = cl->val.clam.lfun;
  761. if (lengthNL (names) != lengthVL (args)) {
  762. printf ("Wrong number of arguments to closure\n");
  763. printf ("names\n");
  764. prNL (names);
  765. printf ("arguments\n");
  766. prVL (args);
  767. longjmp (_EXH, 1);
  768. }
  769. newenv = extendEnv (savedenv, names, args);
  770. return (lfun(newenv));
  771. }
  772. /* prValue - print value val */
  773. void
  774. prValue (VALUE * val)
  775. {
  776. int i;
  777. if (val != NULL) {
  778. switch (val->type) {
  779. case INTV:
  780. printf ("%ld", val->val.ival);
  781. break;
  782. case SYMV:
  783. prString (val->val.sym);
  784. break;
  785. case STRV:
  786. prString (val->val.str);
  787. break;
  788. case LISTV:
  789. i = 0;
  790. putchar ('(');
  791. while (val != NULL) {
  792. i++;
  793. prValue (evalThunk (val->val.lv.car));
  794. putchar (' ');
  795. val = val->val.lv.cdr;
  796. }
  797. printf (")\n");
  798. break;
  799. case PRIMV:
  800. printf ("<primitive: ");
  801. prName ((int) val->val.prim + 1);
  802. putchar ('>');
  803. break;
  804. case ACLV:
  805. printf ("lambda");
  806. prNL(val->val.acl.fun->exp.abs.vars);
  807. break;
  808. case CLAMV:
  809. printf ("<c-lambda-abstraction>");
  810. break;
  811. case THUNKV:
  812. printf ("...");
  813. break;
  814. }
  815. }
  816. }
  817. /* lengthVL - return length of VLIST vl */
  818. long
  819. lengthVL (VLIST * vl)
  820. {
  821. long i = 0;
  822. while (vl != NULL) {
  823. i++;
  824. vl = vl->tail;
  825. }
  826. return i;
  827. }
  828. /* prVL - print list of values */
  829. void
  830. prVL (VLIST * vl)
  831. {
  832. long i = 0;
  833. putchar ('(');
  834. while (vl != NULL) {
  835. i++;
  836. prValue (evalThunk (vl->head));
  837. putchar (' ');
  838. vl = vl->tail;
  839. }
  840. printf (")\n");
  841. }
  842. /*****************************************************************
  843. * LOAD ABSTRACTION FROM FILE *
  844. *****************************************************************/
  845. /* primitive function load (load abstractions from file) */
  846. VALUE *
  847. load (VALUE * val)
  848. {
  849. char *file;
  850. FILE *fis;
  851. EXP *currp;
  852. VALUE *result;
  853. int ret;
  854. if (val->type == STRV) {
  855. file = nameTable[val->val.str - 1];
  856. }
  857. else {
  858. printf ("load: error in argument type\n");
  859. longjmp (_EXH, 1);
  860. }
  861. fis = fopen (file, "r");
  862. parserinit (fis);
  863. while (1) {
  864. currp = readWithoutPrompt ();
  865. result = evalThunk (eval (currp, globalEnv, trueSym));
  866. if ((result->type == STRV) && (result->val.str == eof)) {
  867. fclose (fis);
  868. break;
  869. }
  870. prValue (result);
  871. //printf (".");
  872. }
  873. parserinit (stdin);
  874. return result;
  875. }