eval3.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313
  1. /* eval3.c Copyright (C) 1991-2002 Codemist Ltd */
  2. /*
  3. * Interpreter (part 3).
  4. * Implementations of special forms (interpreted versions).
  5. *
  6. */
  7. /*
  8. * This code may be used and modified, and redistributed in binary
  9. * or source form, subject to the "CCL Public License", which should
  10. * accompany it. This license is a variant on the BSD license, and thus
  11. * permits use of code derived from this in either open and commercial
  12. * projects: but it does require that updates to this code be made
  13. * available back to the originators of the package.
  14. * Before merging other code in with this or linking this code
  15. * with other packages or libraries please check that the license terms
  16. * of the other material are compatible with those of this.
  17. */
  18. /* Signature: 46e5fa5a 08-Apr-2002 */
  19. #include <stdarg.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #ifdef __WATCOMC__
  23. #include <float.h>
  24. #endif
  25. #include "machine.h"
  26. #include "tags.h"
  27. #include "cslerror.h"
  28. #include "externs.h"
  29. #include "arith.h"
  30. #include "entries.h"
  31. #ifdef TIMEOUT
  32. #include "timeout.h"
  33. #endif
  34. #ifndef COMMON
  35. static Lisp_Object plus_fn(Lisp_Object args, Lisp_Object env)
  36. {
  37. Lisp_Object nil = C_nil;
  38. Lisp_Object r;
  39. if (!consp(args)) return fixnum_of_int(0); /* (plus) => 0 */
  40. stackcheck2(0, args, env);
  41. push2(args, env);
  42. r = qcar(args);
  43. r = eval(r, env);
  44. pop2(env, args);
  45. errexit();
  46. args = qcdr(args);
  47. while (consp(args))
  48. { Lisp_Object w;
  49. push3(env, args, r);
  50. w = qcar(args);
  51. w = eval(w, env);
  52. pop(r);
  53. errexitn(2);
  54. if (is_fixnum(r) && is_fixnum(w))
  55. { int32 c = int_of_fixnum(r) + int_of_fixnum(w);
  56. int32 w1 = c & fix_mask;
  57. if (w1 == 0 || w1 == fix_mask) r = fixnum_of_int(c);
  58. else r = plus2(r, w);
  59. }
  60. else r = plus2(r, w);
  61. errexitn(2);
  62. pop2(args, env);
  63. args = qcdr(args);
  64. }
  65. return onevalue(r);
  66. }
  67. static Lisp_Object times_fn(Lisp_Object args, Lisp_Object env)
  68. {
  69. Lisp_Object nil = C_nil;
  70. Lisp_Object r;
  71. if (!consp(args)) return fixnum_of_int(1); /* (times) => 1 */
  72. stackcheck2(0, args, env);
  73. push2(args, env);
  74. r = qcar(args);
  75. r = eval(r, env);
  76. pop2(env, args);
  77. errexit();
  78. args = qcdr(args);
  79. while (consp(args))
  80. { Lisp_Object w;
  81. push3(env, args, r);
  82. w = qcar(args);
  83. w = eval(w, env);
  84. pop(r);
  85. errexitn(2);
  86. r = times2(r, w);
  87. pop2(args, env);
  88. errexit();
  89. args = qcdr(args);
  90. }
  91. return onevalue(r);
  92. }
  93. static Lisp_Object list_fn(Lisp_Object args, Lisp_Object env)
  94. {
  95. Lisp_Object nil = C_nil;
  96. Lisp_Object w1, w2, w3, r = nil;
  97. /*
  98. * I am going to write out the cases of list with 0, 1, 2 or 3
  99. * args specially here, since I expect them to be the more common ones
  100. * and I am generally jumpy about performance. It seems a bit nasty
  101. * to get to an interpreted call to list anyway.
  102. */
  103. if (!consp(args)) return onevalue(nil); /* (list) */
  104. w1 = qcar(args); args = qcdr(args);
  105. if (!consp(args)) /* (list w1) */
  106. { w1 = eval(w1, env);
  107. errexit();
  108. w1 = ncons(w1);
  109. errexit();
  110. return onevalue(w1);
  111. }
  112. w2 = qcar(args); args = qcdr(args);
  113. if (!consp(args)) /* (list w1 w2) */
  114. { push2(env, w2);
  115. w1 = eval(w1, env);
  116. errexitn(2);
  117. w2 = stack[0];
  118. stack[0] = w1;
  119. w2 = eval(w2, stack[-1]);
  120. errexitn(2);
  121. w1 = list2(stack[0], w2);
  122. popv(2);
  123. errexit();
  124. return onevalue(w1);
  125. }
  126. w3 = qcar(args); args = qcdr(args);
  127. if (!is_cons(args)) /* (list w1 w2 w3) */
  128. { push3(env, w2, w3);
  129. w1 = eval(w1, env);
  130. errexitn(3);
  131. w2 = stack[-1];
  132. stack[-1] = w1;
  133. w2 = eval(w2, stack[-2]);
  134. errexitn(3);
  135. w3 = stack[0];
  136. stack[0] = w2;
  137. w3 = eval(w3, stack[-2]);
  138. errexitn(3);
  139. w3 = ncons(w3);
  140. errexitn(3);
  141. w1 = list2star(stack[-1], stack[0], w3);
  142. popv(3);
  143. errexit();
  144. return onevalue(w1);
  145. }
  146. push4(args, env, w1, w2);
  147. w3 = eval(w3, env);
  148. errexitn(4);
  149. push(w3);
  150. w2 = eval(stack[-1], stack[-3]);
  151. errexitn(5);
  152. stack[-1] = w2;
  153. w1 = eval(stack[-2], stack[-3]);
  154. errexitn(5);
  155. r = ncons(w1);
  156. errexitn(5);
  157. pop2(w3, w2);
  158. r = list2star(w3, w2, r);
  159. errexitn(3);
  160. pop3(w1, env, args);
  161. while (consp(args))
  162. { Lisp_Object w;
  163. push3(env, args, r);
  164. w = qcar(args);
  165. w = eval(w, env);
  166. pop(r);
  167. errexitn(2);
  168. r = cons(w, r);
  169. pop2(args, env);
  170. errexit();
  171. args = qcdr(args);
  172. }
  173. return onevalue(nreverse(r));
  174. }
  175. static Lisp_Object liststar_fn(Lisp_Object args, Lisp_Object env)
  176. {
  177. Lisp_Object nil = C_nil;
  178. Lisp_Object r = nil;
  179. if (!consp(args)) return aerror("list*");
  180. do
  181. { Lisp_Object w;
  182. push3(env, args, r);
  183. w = qcar(args);
  184. w = eval(w, env);
  185. pop(r);
  186. errexitn(2);
  187. r = cons(w, r);
  188. pop2(args, env);
  189. errexit();
  190. args = qcdr(args);
  191. } while (consp(args));
  192. args = qcar(r);
  193. r = qcdr(r);
  194. while (r != nil)
  195. { Lisp_Object c = r;
  196. r = qcdr(r);
  197. qcdr(c) = args;
  198. args = c;
  199. }
  200. return onevalue(args);
  201. }
  202. #endif
  203. #define BODY_LET 0
  204. #define BODY_COMPILER_LET 1
  205. #define BODY_PROG 2
  206. #ifdef COMMON
  207. static Lisp_Object macrolet_fn(Lisp_Object args, Lisp_Object env)
  208. {
  209. Lisp_Object d, nil = C_nil;
  210. if (!consp(args)) return onevalue(nil);
  211. stackcheck2(0, args, env);
  212. d = qcar(args); /* The bunch of definitions */
  213. while (consp(d))
  214. { Lisp_Object w = qcar(d); /* w = (name bvl ...) */
  215. if (consp(w) && consp(qcdr(w)))
  216. {
  217. /*
  218. * Here I need to call (expand-definer <form> nil) to map
  219. * macro specifications with all the possible magic options into ones
  220. * which just take 2 args, a form and an environment.
  221. */
  222. push2(args, env);
  223. w = cons(expand_def_symbol, w);
  224. errexitn(2);
  225. w = Lfuncalln(nil, 3, expand_def_symbol, w, nil);
  226. errexitn(2);
  227. /*
  228. * I expect expand-definer to return either
  229. * (~~defmacro name bvl ...)
  230. * OR (progn XXX (~~defmacro name bvl ...))
  231. * where XXX is exactly one form.
  232. */
  233. if (qcar(w) == progn_symbol)
  234. w = qcar(qcdr(qcdr(w)));
  235. w = qcdr(w);
  236. w = cons(qcdr(w), qcar(w));
  237. errexitn(2);
  238. pop2(env, args);
  239. env = cons(w, env);
  240. errexit();
  241. }
  242. d = qcdr(d);
  243. }
  244. return let_fn_1(nil, qcdr(args), env, BODY_LET);
  245. }
  246. #endif
  247. #ifdef COMMON
  248. static Lisp_Object mv_prog1_fn(Lisp_Object args, Lisp_Object env)
  249. {
  250. Lisp_Object r, rl, nil = C_nil;
  251. int nargs, i;
  252. if (!consp(args)) return onevalue(nil);
  253. stackcheck2(0, args, env);
  254. push2(args, env);
  255. r = qcar(args);
  256. r = eval(r, env);
  257. pop2(env, args);
  258. errexit();
  259. rl = nil;
  260. nargs = exit_count;
  261. push(r);
  262. /*
  263. * I could use the Lisp stack to save things here, but I hope that this
  264. * function is not used much and performance will not matter.
  265. */
  266. for (i=nargs; i>=2; i--)
  267. rl = cons_no_gc((&mv_2)[i-2], rl);
  268. rl = cons_gc_test(rl);
  269. errexitn(1);
  270. push(rl);
  271. while (is_cons(args = qcdr(args)) && args!=nil)
  272. { Lisp_Object w;
  273. push2(args, env);
  274. w = qcar(args);
  275. eval(w, env);
  276. pop2(env, args);
  277. errexitn(2);
  278. }
  279. pop(rl);
  280. for (i = 2; i<=nargs; i++)
  281. { (&mv_2)[i-2] = qcar(rl);
  282. rl = qcdr(rl);
  283. }
  284. pop(r);
  285. return nvalues(r, nargs);
  286. }
  287. #endif
  288. static Lisp_Object or_fn(Lisp_Object args, Lisp_Object env)
  289. /* also needs to be a macro for Common Lisp */
  290. {
  291. Lisp_Object nil = C_nil;
  292. if (!consp(args)) return onevalue(nil);
  293. stackcheck2(0, args, env);
  294. for (;;)
  295. { Lisp_Object v = qcar(args);
  296. args = qcdr(args);
  297. if (!consp(args)) return eval(v, env);
  298. push2(args, env);
  299. v = eval(v, env);
  300. pop2(env, args);
  301. errexit();
  302. if (v != nil) return onevalue(v);
  303. }
  304. }
  305. static Lisp_Object prog_fn(Lisp_Object args, Lisp_Object env)
  306. {
  307. Lisp_Object p, nil = C_nil;
  308. if (!consp(args) || !consp(qcdr(args))) return onevalue(nil);
  309. stackcheck2(0, args, env);
  310. push3(nil, args, env);
  311. #define env stack[0]
  312. #define args stack[-1]
  313. #define my_tag stack[-2]
  314. /*
  315. * I need to augment the (lexical) environment with a null block
  316. * tag so that (return ..) will work as required. See block_fn for
  317. * further elaboration since (block ..) is the main way of introducing
  318. * new block tags.
  319. */
  320. my_tag = cons(fixnum_of_int(0), nil);
  321. errexitn(3);
  322. env = cons(my_tag, env);
  323. errexitn(3);
  324. p = let_fn_1(qcar(args), qcdr(args), env, BODY_PROG);
  325. nil = C_nil;
  326. if (exception_pending())
  327. { flip_exception(); /* Temp restore it */
  328. qcar(my_tag) = fixnum_of_int(2); /* Invalidate */
  329. if (exit_reason == UNWIND_RETURN && exit_tag == my_tag)
  330. { exit_reason = UNWIND_NULL; /* not strictly needed - but tidy */
  331. popv(3);
  332. return exit_value; /* exit_count already OK here */
  333. }
  334. if ((exit_reason & UNWIND_ERROR) != 0)
  335. { err_printf("\nEvaluating: ");
  336. loop_print_error(args);
  337. }
  338. flip_exception(); /* re-instate exit condition */
  339. popv(3);
  340. return nil;
  341. }
  342. popv(3);
  343. return onevalue(nil);
  344. #undef env
  345. #undef args
  346. #undef my_tag
  347. }
  348. #ifdef COMMON
  349. /*--
  350. *-- At one time I though I might implement PROG* in the kernel here, but
  351. *-- now it seems at least as reasonable to implement it is a Lisp-coded
  352. *-- macro that expands to BLOCK, LET* and TAGBODY, thus meaning that the
  353. *-- code that was supposed to be provided here is pretty-well irrelevant.
  354. *--
  355. *-- static Lisp_Object progstar_fn(Lisp_Object args, Lisp_Object env)
  356. *-- /*
  357. *-- * /* At present this is WRONG in that it is just a copy of prog_fn,
  358. *-- * so it awaits re-work to make the bindings happen in serial rather
  359. *-- * than parallel..
  360. *-- * /
  361. *-- {
  362. *-- Lisp_Object p, nil = C_nil;
  363. *-- if (!consp(args) || !consp(qcdr(args))) return onevalue(nil);
  364. *-- stackcheck2(0, args, env);
  365. *-- push3(nil, args, env);
  366. *-- #define env stack[0]
  367. *-- #define args stack[-1]
  368. *-- #define my_tag stack[-2]
  369. *-- /*
  370. *-- * I need to augment the (lexical) environment with a null block
  371. *-- * tag so that (return ..) will work as required. See block_fn for
  372. *-- * further elaboration since (block ..) is the main way of introducing
  373. *-- * new block tags.
  374. *-- * /
  375. *-- my_tag = cons(fixnum_of_int(0), nil);
  376. *-- errexitn(3);
  377. *-- env = cons(my_tag, env);
  378. *-- errexitn(3);
  379. *-- p = let_fn_1(qcar(args), qcdr(args), env, BODY_PROG);
  380. *-- nil = C_nil;
  381. *-- if (exception_pending())
  382. *-- { flip_exception(); /* Temp restore it * /
  383. *-- qcar(my_tag) = fixnum_of_int(2); /* Invalidate * /
  384. *-- if (exit_reason == UNWIND_RETURN && exit_tag == my_tag)
  385. *-- { exit_reason = UNWIND_NULL; /* not strictly needed - but tidy * /
  386. *-- popv(3);
  387. *-- return exit_value;
  388. *-- }
  389. *-- if ((exit_reason & UNWIND_ERROR) != 0)
  390. *-- { err_printf("\nEvaluating: ");
  391. *-- loop_print_error(qcar(args));
  392. *-- }
  393. *-- flip_exception(); /* re-instate exit condition * /
  394. *-- popv(3);
  395. *-- return nil;
  396. *-- }
  397. *-- popv(3);
  398. *-- return onevalue(nil);
  399. *-- #undef env
  400. *-- #undef args
  401. *-- #undef my_tag
  402. *-- }
  403. *--
  404. */
  405. #endif
  406. Lisp_Object progn_fn(Lisp_Object args, Lisp_Object env)
  407. {
  408. Lisp_Object f, nil = C_nil;
  409. if (!consp(args)) return onevalue(nil);
  410. stackcheck2(0, args, env);
  411. f = nil;
  412. for (;;)
  413. { f = qcar(args);
  414. args = qcdr(args);
  415. if (!consp(args)) break;
  416. push3(args, env, f);
  417. voideval(f, env);
  418. pop3(f, env, args);
  419. nil = C_nil;
  420. if (exception_pending())
  421. { flip_exception();
  422. if ((exit_reason & UNWIND_ERROR) != 0)
  423. { err_printf("\nEvaluating: ");
  424. loop_print_error(f);
  425. }
  426. flip_exception();
  427. return nil; /* premature exit */
  428. }
  429. }
  430. return eval(f, env); /* tail call on last item in the progn */
  431. }
  432. static Lisp_Object prog1_fn(Lisp_Object args, Lisp_Object env)
  433. /*
  434. * prog1 and prog2 will be implemented as macros for Common Lisp,
  435. * and are here implemented as special forms too in the expectation
  436. * that that will be good for performance.
  437. */
  438. {
  439. Lisp_Object f, nil = C_nil;
  440. if (!consp(args)) return onevalue(nil); /* (prog1) -> nil */
  441. stackcheck2(0, args, env);
  442. push2(args, env);
  443. f = qcar(args);
  444. f = eval(f, env); /* first arg */
  445. pop2(env, args);
  446. push(f);
  447. errexit();
  448. for (;;)
  449. { args = qcdr(args);
  450. if (!consp(args)) break;
  451. push2(args, env);
  452. { Lisp_Object w = qcar(args);
  453. voideval(w, env);
  454. }
  455. pop2(env, args);
  456. errexitn(1);
  457. }
  458. pop(f);
  459. return onevalue(f); /* always hands back just 1 value */
  460. }
  461. static Lisp_Object prog2_fn(Lisp_Object args, Lisp_Object env)
  462. {
  463. Lisp_Object f, nil = C_nil;
  464. if (!consp(args)) return onevalue(nil); /* (prog2) -> nil */
  465. stackcheck2(0, args, env);
  466. push2(args, env);
  467. args = qcar(args);
  468. voideval(args, env); /* discard first arg */
  469. pop2(env, args);
  470. errexit();
  471. args = qcdr(args);
  472. if (!consp(args)) return onevalue(nil); /* (prog2 x) -> nil */
  473. push2(args, env);
  474. f = qcar(args);
  475. f = eval(f, env); /* second arg */
  476. pop2(env, args);
  477. push(f);
  478. errexit();
  479. for (;;)
  480. { args = qcdr(args);
  481. if (!consp(args)) break;
  482. push2(args, env);
  483. args = qcar(args);
  484. voideval(args, env);
  485. pop2(env, args);
  486. errexitn(1);
  487. }
  488. pop(f);
  489. return onevalue(f); /* always hands back just 1 value */
  490. }
  491. #ifdef COMMON
  492. static Lisp_Object progv_fn(Lisp_Object args, Lisp_Object env)
  493. {
  494. Lisp_Object syms, vals, specenv, nil = C_nil, w;
  495. if (!consp(args)) return onevalue(nil);
  496. stackcheck2(0, args, env);
  497. syms = vals = specenv = nil;
  498. syms = qcar(args);
  499. args = qcdr(args);
  500. push5(args, env, syms, vals, specenv);
  501. #define specenv stack[0]
  502. #define vals stack[-1]
  503. #define syms stack[-2]
  504. #define env stack[-3]
  505. #define args stack[-4]
  506. syms = eval(syms, env);
  507. nil = C_nil;
  508. if (exception_pending() || !consp(args)) { popv(5); return nil; }
  509. w = qcar(args);
  510. args = qcdr(args);
  511. vals = eval(w, env);
  512. nil = C_nil;
  513. if (exception_pending() || !consp(args)) { popv(5); return nil; }
  514. while (consp(syms))
  515. { Lisp_Object v = qcar(syms);
  516. Lisp_Object w1;
  517. if (consp(vals))
  518. { w = qcar(vals);
  519. vals = qcdr(vals);
  520. }
  521. else w = unset_var;
  522. syms = qcdr(syms);
  523. if (!is_symbol(v)) continue;
  524. w1 = cons(v, qvalue(v));
  525. /*
  526. * If I were to take the error exit here then some variables would have
  527. * been set to their new values and some not. That would be a mess!
  528. */
  529. errexitn(5);
  530. qvalue(v) = w;
  531. specenv = cons(w1, specenv);
  532. errexitn(5);
  533. }
  534. args = progn_fn(args, env);
  535. nil = C_nil;
  536. if (exception_pending())
  537. { flip_exception();
  538. while (specenv != nil)
  539. { Lisp_Object p = qcar(specenv);
  540. qvalue(qcar(p)) = qcdr(p);
  541. specenv = qcdr(specenv);
  542. }
  543. flip_exception();
  544. popv(5);
  545. return nil;
  546. }
  547. while (specenv != nil)
  548. { Lisp_Object p = qcar(specenv);
  549. qvalue(qcar(p)) = qcdr(p);
  550. specenv = qcdr(specenv);
  551. }
  552. popv(4);
  553. #undef specenv
  554. #undef vals
  555. #undef syms
  556. #undef env
  557. #undef args
  558. pop(vals);
  559. return vals;
  560. }
  561. #endif
  562. Lisp_Object quote_fn(Lisp_Object args, Lisp_Object env)
  563. {
  564. Lisp_Object nil = C_nil;
  565. CSL_IGNORE(env);
  566. if (consp(args) && qcdr(args) == nil) return onevalue(qcar(args));
  567. return aerror("quote");
  568. }
  569. static Lisp_Object return_fn(Lisp_Object args, Lisp_Object env)
  570. {
  571. /*
  572. * First check that the block name (nil in this case) is lexically available
  573. */
  574. Lisp_Object p, nil = C_nil;
  575. stackcheck2(0, args, env);
  576. for(p=env; consp(p); p=qcdr(p))
  577. { Lisp_Object w = qcar(p);
  578. if (!consp(w)) continue;
  579. if (qcar(w) == fixnum_of_int(0) && qcdr(w) == nil)
  580. { p = w;
  581. goto tag_found;
  582. }
  583. }
  584. return error(1, err_block_tag, nil);
  585. tag_found:
  586. if (consp(args))
  587. {
  588. push(p);
  589. p = qcar(args);
  590. env = eval(p, env);
  591. pop(p);
  592. errexit();
  593. exit_value = env;
  594. #ifndef COMMON
  595. exit_count = 1;
  596. #else
  597. /* exit_count was left set by the call to eval */
  598. #endif
  599. }
  600. else
  601. { exit_value = nil;
  602. exit_count = 1;
  603. }
  604. exit_tag = p;
  605. exit_reason = UNWIND_RETURN;
  606. flip_exception();
  607. return nil;
  608. }
  609. #ifdef COMMON
  610. static Lisp_Object return_from_fn(Lisp_Object args, Lisp_Object env)
  611. {
  612. Lisp_Object p, tag, nil = C_nil;
  613. stackcheck2(0, args, env);
  614. if (!consp(args)) tag = nil;
  615. else
  616. { tag = qcar(args);
  617. args = qcdr(args);
  618. }
  619. for(p=env; consp(p); p=qcdr(p))
  620. { Lisp_Object w = qcar(p);
  621. if (!consp(w)) continue;
  622. if (qcar(w) == fixnum_of_int(0) && qcdr(w) == tag)
  623. { p = w;
  624. goto tag_found;
  625. }
  626. }
  627. return error(1, err_block_tag, tag);
  628. tag_found:
  629. if (consp(args))
  630. {
  631. push(p);
  632. p = qcar(args);
  633. env = eval(p, env);
  634. pop(p);
  635. errexit();
  636. exit_value = env;
  637. #ifndef COMMON
  638. exit_count = 1;
  639. #else
  640. /* exit_count left set by eval */
  641. #endif
  642. }
  643. else
  644. { exit_value = nil;
  645. exit_count = 1;
  646. }
  647. exit_tag = p;
  648. exit_reason = UNWIND_RETURN;
  649. flip_exception();
  650. return nil;
  651. }
  652. #endif
  653. static Lisp_Object setq_fn(Lisp_Object args, Lisp_Object env)
  654. {
  655. Lisp_Object nil = C_nil;
  656. Lisp_Object var, val = nil;
  657. stackcheck2(0, args, env);
  658. while (consp(args))
  659. { var = qcar(args);
  660. if (!is_symbol(var) || var == nil || var == lisp_true)
  661. return aerror("setq (bad variable)");
  662. args = qcdr(args);
  663. if (consp(args))
  664. { push3(args, env, var);
  665. val = qcar(args);
  666. val = eval(val, env);
  667. pop3(var, env, args);
  668. errexit();
  669. args = qcdr(args);
  670. }
  671. else val = nil;
  672. #ifndef COMMON
  673. qvalue(var) = val;
  674. #else
  675. if (qheader(var) & SYM_SPECIAL_VAR) qvalue(var) = val;
  676. else
  677. { Lisp_Object p = env, w;
  678. for (;;)
  679. { if (!consp(p))
  680. {
  681. #ifndef COMMON
  682. qheader(var) |= SYM_SPECIAL_VAR;
  683. push3(args, env, var);
  684. debug_printf("\n+++++ "); loop_print_debug(var);
  685. debug_printf(" proclaimed SPECIAL by SETQ\n");
  686. pop3(var, env, args);
  687. errexit();
  688. #endif
  689. qvalue(var) = val;
  690. break;
  691. }
  692. w = qcar(p);
  693. if (qcar(w) == var)
  694. {
  695. if (qcdr(w) == work_symbol) qvalue(var) = val;
  696. else qcdr(w) = val;
  697. break;
  698. }
  699. p = qcdr(p);
  700. }
  701. }
  702. #endif
  703. }
  704. return onevalue(val);
  705. }
  706. static Lisp_Object noisy_setq_fn(Lisp_Object args, Lisp_Object env)
  707. {
  708. Lisp_Object nil = C_nil;
  709. Lisp_Object var, val = nil;
  710. stackcheck2(0, args, env);
  711. while (consp(args))
  712. { var = qcar(args);
  713. if (!is_symbol(var) || var == nil || var == lisp_true)
  714. return aerror("setq (bad variable)");
  715. args = qcdr(args);
  716. if (consp(args))
  717. { push3(args, env, var);
  718. val = qcar(args);
  719. val = eval(val, env);
  720. pop3(var, env, args);
  721. errexit();
  722. args = qcdr(args);
  723. }
  724. else val = nil;
  725. push4(var, env, args, val);
  726. loop_print_trace(var);
  727. errexitn(4);
  728. trace_printf(" := ");
  729. loop_print_trace(stack[0]);
  730. errexitn(4);
  731. trace_printf("\n");
  732. pop4(val, args, env, var);
  733. #ifndef COMMON
  734. qvalue(var) = val;
  735. #else
  736. if (qheader(var) & SYM_SPECIAL_VAR) qvalue(var) = val;
  737. else
  738. { Lisp_Object p = env, w;
  739. for (;;)
  740. { if (!consp(p))
  741. {
  742. #ifndef COMMON
  743. qheader(var) |= SYM_SPECIAL_VAR;
  744. push3(args, env, var);
  745. debug_printf("\n+++++ "); loop_print_debug(var);
  746. debug_printf(" proclaimed SPECIAL by SETQ\n");
  747. pop3(var, env, args);
  748. errexit();
  749. #endif
  750. qvalue(var) = val;
  751. break;
  752. }
  753. w = qcar(p);
  754. if (qcar(w) == var)
  755. {
  756. if (qcdr(w) == work_symbol) qvalue(var) = val;
  757. else qcdr(w) = val;
  758. break;
  759. }
  760. p = qcdr(p);
  761. }
  762. }
  763. #endif
  764. }
  765. return onevalue(val);
  766. }
  767. Lisp_Object tagbody_fn(Lisp_Object args, Lisp_Object env)
  768. {
  769. Lisp_Object f, p, my_env, nil = C_nil;
  770. /*
  771. * Bind the labels that occur in this block. Note that I invalidate
  772. * these bindings if I ever exit from this block, so that nobody
  773. * even thinks that they can use (go xx) to get back in.
  774. */
  775. stackcheck2(0, args, env);
  776. f = nil;
  777. push2(env, args);
  778. for (p=args; consp(p); p=qcdr(p))
  779. { Lisp_Object w = qcar(p);
  780. if (!consp(w))
  781. { Lisp_Object w1;
  782. push3(f, p, env);
  783. w1 = cons(fixnum_of_int(1), p);
  784. pop(env);
  785. nil = C_nil;
  786. if (!exception_pending()) env = cons(w1, env);
  787. pop2(p, f);
  788. errexitn(2);
  789. }
  790. }
  791. pop(args);
  792. /*
  793. * (go xx) sets exit_tag to xx, which is then noticed next time tagbody
  794. * is about to do anything.
  795. */
  796. for (p=args;;p = qcdr(p))
  797. { nil = C_nil;
  798. if (exception_pending())
  799. { flip_exception();
  800. pop(my_env);
  801. if (exit_reason != UNWIND_GO)
  802. {
  803. while (env != my_env)
  804. { qcar(qcar(env)) = fixnum_of_int(2);
  805. env = qcdr(env);
  806. }
  807. if ((exit_reason & UNWIND_ERROR) != 0)
  808. { err_printf("\nEvaluating: ");
  809. loop_print_error(f);
  810. ignore_exception();
  811. }
  812. flip_exception();
  813. return nil; /* re-instate exit condition */
  814. }
  815. else
  816. { for (p=env;;p=qcdr(p))
  817. /*
  818. * If the target of (go xx) is not found then tagbody returns without
  819. * clearing exit_tag, thus giving an enclosing tagbody a chance to notice
  820. * the problem and look for the label.
  821. */
  822. { if (p == my_env) /* Not to a tag in this tagbody */
  823. { while (env != my_env)
  824. { qcar(qcar(env)) = fixnum_of_int(2);
  825. env = qcdr(env);
  826. }
  827. if ((exit_reason & UNWIND_ERROR) != 0)
  828. { err_printf("\nEvaluating: ");
  829. loop_print_error(f);
  830. ignore_exception();
  831. }
  832. flip_exception();
  833. return nil;
  834. }
  835. if (exit_tag == qcar(p))
  836. { p = qcdr(qcdr(exit_tag));
  837. exit_tag = nil;
  838. exit_reason = UNWIND_NULL;
  839. push(my_env);
  840. break; /* Success! */
  841. }
  842. }
  843. }
  844. }
  845. if (!consp(p))
  846. { pop(my_env);
  847. while (env != my_env)
  848. { qcar(qcar(env)) = fixnum_of_int(2);
  849. env = qcdr(env);
  850. }
  851. return onevalue(nil);
  852. }
  853. if (is_cons(f = qcar(p)) && f!=nil)
  854. { push3(p, env, f);
  855. voideval(f, env);
  856. pop3(f, env, p);
  857. }
  858. }
  859. }
  860. #ifdef COMMON
  861. static Lisp_Object the_fn(Lisp_Object args, Lisp_Object env)
  862. /*
  863. * in effect an identity function for the present
  864. */
  865. {
  866. Lisp_Object nil = C_nil;
  867. if (!consp(args)) return onevalue(nil);
  868. args = qcdr(args);
  869. if (!consp(args)) return onevalue(nil);
  870. args = qcar(args);
  871. return eval(args, env);
  872. }
  873. #endif
  874. static Lisp_Object throw_fn(Lisp_Object args, Lisp_Object env)
  875. {
  876. Lisp_Object tag, p, nil = C_nil;
  877. if (!consp(args)) return aerror("throw");
  878. stackcheck2(0, args, env);
  879. tag = qcar(args);
  880. args = qcdr(args);
  881. push2(args, env);
  882. tag = eval(tag, env);
  883. pop2(env, args);
  884. errexit();
  885. for (p = catch_tags; p!=nil; p=qcdr(p))
  886. if (tag == qcar(p)) goto tag_found;
  887. return aerror("throw: tag not found");
  888. tag_found:
  889. if (consp(args))
  890. {
  891. push(p);
  892. tag = qcar(args);
  893. tag = eval(tag, env);
  894. pop(p);
  895. errexit();
  896. exit_value = tag;
  897. #ifndef COMMON
  898. exit_count = 1;
  899. #else
  900. /* exit_count left set by eval */
  901. #endif
  902. }
  903. else
  904. { exit_value = nil;
  905. exit_count = 1;
  906. }
  907. exit_tag = p;
  908. exit_reason = UNWIND_THROW;
  909. flip_exception();
  910. return nil;
  911. }
  912. static Lisp_Object unless_fn(Lisp_Object args, Lisp_Object env)
  913. {
  914. Lisp_Object w, nil = C_nil;
  915. if (!consp(args)) return onevalue(nil);
  916. stackcheck2(0, args, env);
  917. push2(args, env);
  918. w = qcar(args);
  919. w = eval(w, env);
  920. pop2(env, args);
  921. errexit();
  922. if (w != nil) return onevalue(nil);
  923. else return progn_fn(qcdr(args), env);
  924. }
  925. static Lisp_Object unwind_protect_fn(Lisp_Object args, Lisp_Object env)
  926. {
  927. Lisp_Object nil = C_nil;
  928. Lisp_Object r = nil ,rl = nil;
  929. int nargs = 0, i;
  930. if (!consp(args)) return onevalue(nil);
  931. stackcheck2(0, args, env);
  932. push2(args, env);
  933. r = qcar(args);
  934. r = eval(r, env);
  935. pop2(env, args);
  936. nil = C_nil;
  937. if (exception_pending())
  938. { Lisp_Object xt, xv;
  939. int xc, xr;
  940. /*
  941. * Here I am in the process of exiting because of a throw, return-from,
  942. * go or error. I need to save all the internal stuff that tells me
  943. * what is going on so I can restore it after the clean-up forms have been
  944. * processed. The values involved are:
  945. * (a) exit_tag marks use of go, return-from or throw
  946. * (b) exit_value first result value (throw, return-from)
  947. * (c) exit_count number of values (throw, return-from)
  948. * (d) mv2,... as indicated by exit_count
  949. * (e) exit_reason what it says.
  950. */
  951. flip_exception();
  952. xv = exit_value;
  953. xt = exit_tag;
  954. xc = exit_count;
  955. xr = exit_reason;
  956. push2(xv, xt);
  957. for (i=xc; i>=2; i--)
  958. rl = cons_no_gc((&mv_2)[i-2], rl);
  959. rl = cons_gc_test(rl);
  960. errexitn(2);
  961. push(rl);
  962. while (is_cons(args = qcdr(args)) && args!=nil)
  963. { Lisp_Object w = qcar(args);
  964. push2(args, env);
  965. voideval(w, env);
  966. pop2(env, args);
  967. errexitn(3);
  968. }
  969. pop3(rl, xt, xv);
  970. for (i = 2; i<=xc; i++)
  971. { (&mv_2)[i-2] = qcar(rl);
  972. rl = qcdr(rl);
  973. }
  974. exit_value = xv;
  975. exit_tag = xt;
  976. exit_count = xc;
  977. exit_reason = xr;
  978. flip_exception();
  979. return nil;
  980. }
  981. /*
  982. * Now code (just like multiple-value-prog1) that evaluates the
  983. * cleanup forms in the case that the protected form exits normally.
  984. */
  985. #ifndef COMMON
  986. nargs = 1; /* Just one value returned */
  987. #else
  988. nargs = exit_count;
  989. #endif
  990. push2(args, env);
  991. for (i=nargs; i>=2; i--)
  992. rl = cons_no_gc((&mv_2)[i-2], rl);
  993. rl = cons_gc_test(rl);
  994. errexitn(2);
  995. push(rl);
  996. #define env stack[-1]
  997. #define args stack[-2]
  998. while (is_cons(args = qcdr(args)) && args!=nil)
  999. { Lisp_Object w = qcar(args);
  1000. voideval(w, env);
  1001. errexitn(3);
  1002. }
  1003. #undef env
  1004. #undef args
  1005. pop(rl);
  1006. popv(2);
  1007. for (i = 2; i<=nargs; i++)
  1008. { (&mv_2)[i-2] = qcar(rl);
  1009. rl = qcdr(rl);
  1010. }
  1011. return nvalues(r, nargs);
  1012. }
  1013. /*
  1014. * Errorset is not defined as part of COMMON Lisp but I want it in
  1015. * any Lisp system that I use notwithstanding that.
  1016. */
  1017. #ifndef __cplusplus
  1018. jmp_buf *errorset_buffer;
  1019. #endif
  1020. char *errorset_msg;
  1021. static char signal_msg[32];
  1022. #ifdef __WATCOMC__
  1023. void low_level_signal_handler(int code)
  1024. #else
  1025. void MS_CDECL low_level_signal_handler(int code)
  1026. #endif
  1027. {
  1028. Lisp_Object nil;
  1029. #ifdef __WATCOMC__
  1030. _fpreset();
  1031. #endif
  1032. ignore_exception();
  1033. if (miscflags & (HEADLINE_FLAG|ALWAYS_NOISY))
  1034. switch (code)
  1035. {
  1036. default:
  1037. sprintf(signal_msg, "Signal (code=%d)", code);
  1038. errorset_msg = signal_msg;
  1039. break;
  1040. case SIGFPE:
  1041. errorset_msg = "Floating point exception";
  1042. break;
  1043. case SIGSEGV:
  1044. errorset_msg = "Memory access violation";
  1045. break;
  1046. #ifdef SIGBUS
  1047. case SIGBUS:
  1048. errorset_msg = "Bus error";
  1049. break;
  1050. #endif
  1051. #ifdef SIGILL
  1052. case SIGILL:
  1053. errorset_msg = "Illegal instruction";
  1054. break;
  1055. #endif
  1056. }
  1057. #ifdef __cplusplus
  1058. throw "low_level_signal_handler";
  1059. #else
  1060. longjmp(*errorset_buffer, 1);
  1061. #endif
  1062. }
  1063. void unwind_stack(Lisp_Object *entry_stack, CSLbool findcatch)
  1064. {
  1065. Lisp_Object *sp = stack;
  1066. while (sp != entry_stack)
  1067. { Lisp_Object bv, w;
  1068. int32 n;
  1069. w = *sp--;
  1070. if (findcatch && w == SPID_CATCH) break;
  1071. if (w == (Lisp_Object)SPID_FBIND)
  1072. {
  1073. /*
  1074. * Here I have found some fluid binding that need to be unwound. The code
  1075. * here is similar to that for FREERSTR.
  1076. */
  1077. bv = *sp--;
  1078. n = length_of_header(vechdr(bv));
  1079. while (n>CELL)
  1080. { Lisp_Object v = *(Lisp_Object *)(
  1081. (intxx)bv + n - (CELL + TAG_VECTOR));
  1082. n -= CELL;
  1083. qvalue(v) = *sp--;
  1084. }
  1085. }
  1086. else if (w == (Lisp_Object)SPID_PVBIND)
  1087. { bv = *sp--;
  1088. while (bv != C_nil)
  1089. { Lisp_Object w = qcar(bv);
  1090. qvalue(qcar(w)) = qcdr(w);
  1091. bv = qcdr(bv);
  1092. }
  1093. }
  1094. }
  1095. /*
  1096. * If "findcatch" is true this code must actually update the stack pointer -
  1097. * otherwise it must not. Ugly! The only use with findcatch set true is
  1098. * from the bytecode interpreter (bytes1.c)
  1099. */
  1100. if (findcatch) stack = sp;
  1101. }
  1102. Lisp_Object MS_CDECL Lerrorsetn(Lisp_Object env, int nargs, ...)
  1103. /*
  1104. * This is not a special form, but is put into the code here because,
  1105. * like unwind-protect, it has to re-gain control after an evaluation
  1106. * error.
  1107. */
  1108. {
  1109. Lisp_Object r, nil = C_nil, form, fg1, fg2;
  1110. va_list a;
  1111. Lisp_Object *save;
  1112. unsigned32 flags = miscflags;
  1113. #ifndef __cplusplus
  1114. jmp_buf this_level, *saved_buffer = errorset_buffer;
  1115. #endif
  1116. if (nargs < 1 || nargs > 3) return aerror("errorset");
  1117. va_start(a, nargs);
  1118. form = va_arg(a, Lisp_Object);
  1119. fg1 = fg2 = lisp_true;
  1120. if (nargs >= 2)
  1121. { fg1 = fg2 = va_arg(a, Lisp_Object);
  1122. if (nargs >= 3) fg2 = va_arg(a, Lisp_Object);
  1123. }
  1124. va_end(a);
  1125. miscflags &= ~(HEADLINE_FLAG | MESSAGES_FLAG);
  1126. if (fg1 != nil) miscflags |= HEADLINE_FLAG;
  1127. if (fg2 != nil) miscflags |= MESSAGES_FLAG;
  1128. push2(codevec, litvec);
  1129. save = stack;
  1130. stackcheck2(2, form, env);
  1131. errorset_msg = NULL;
  1132. #ifdef __cplusplus
  1133. try
  1134. #else
  1135. if (!setjmp(this_level))
  1136. #endif
  1137. {
  1138. #ifndef __cplusplus
  1139. errorset_buffer = &this_level;
  1140. #endif
  1141. r = eval(form, env);
  1142. #ifndef __cplusplus
  1143. errorset_buffer = saved_buffer;
  1144. #endif
  1145. nil = C_nil;
  1146. if (exception_pending())
  1147. { flip_exception();
  1148. pop2(litvec, codevec);
  1149. miscflags = (flags & ~GC_MSG_BITS) | (miscflags & GC_MSG_BITS);
  1150. switch (exit_reason)
  1151. {
  1152. case UNWIND_RESTART:
  1153. flip_exception();
  1154. return nil; /* Not catchable */
  1155. default:break;
  1156. }
  1157. if (consp(exit_value)) exit_value = nil;
  1158. return onevalue(exit_value);
  1159. }
  1160. pop2(litvec, codevec);
  1161. miscflags = (flags & ~GC_MSG_BITS) | (miscflags & GC_MSG_BITS);
  1162. r = ncons(r);
  1163. errexit();
  1164. return onevalue(r);
  1165. }
  1166. #ifdef __cplusplus
  1167. catch (char *)
  1168. #else
  1169. else
  1170. #endif
  1171. { if (errorset_msg != NULL)
  1172. { term_printf("\n%s detected\n", errorset_msg);
  1173. errorset_msg = NULL;
  1174. }
  1175. /*
  1176. * Worry about restoration of fluids bound before the exception
  1177. * forced unwinding. All pretty dreadful, I think. If I leave fluid
  1178. * unbind information interleaved on the stack I could cope with it
  1179. * here I think... but I have not done so yet.
  1180. */
  1181. unwind_stack(save, NO);
  1182. stack = save;
  1183. nil = C_nil;
  1184. pop2(litvec, codevec);
  1185. #ifndef __cplusplus
  1186. errorset_buffer = saved_buffer;
  1187. #endif
  1188. signal(SIGFPE, low_level_signal_handler);
  1189. #ifdef __WATCOMC__
  1190. _control87(_EM_OVERFLOW | _EM_INVALID | _EM_DENORMAL |
  1191. _EM_ZERODIVIDE | _EM_INEXACT | _EM_UNDERFLOW,
  1192. _MCW_EM);
  1193. #endif
  1194. if (segvtrap) signal(SIGSEGV, low_level_signal_handler);
  1195. #ifdef SIGBUS
  1196. if (segvtrap) signal(SIGBUS, low_level_signal_handler);
  1197. #endif
  1198. #ifdef SIGILL
  1199. if (segvtrap) signal(SIGILL, low_level_signal_handler);
  1200. #endif
  1201. return onevalue(nil);
  1202. }
  1203. }
  1204. Lisp_Object Lerrorset1(Lisp_Object nil, Lisp_Object form)
  1205. {
  1206. return Lerrorsetn(nil, 3, form, nil, nil);
  1207. }
  1208. Lisp_Object Lerrorset2(Lisp_Object nil, Lisp_Object form, Lisp_Object ffg1)
  1209. {
  1210. return Lerrorsetn(nil, 3, form, ffg1, nil);
  1211. }
  1212. static Lisp_Object when_fn(Lisp_Object args, Lisp_Object env)
  1213. {
  1214. Lisp_Object w, nil = C_nil;
  1215. if (!consp(args)) return onevalue(nil);
  1216. stackcheck2(0, args, env);
  1217. push2(args, env);
  1218. w = qcar(args);
  1219. w = eval(w, env);
  1220. pop2(env, args);
  1221. errexit();
  1222. if (w == nil) return onevalue(nil);
  1223. else return progn_fn(qcdr(args), env);
  1224. }
  1225. setup_type const eval3_setup[] =
  1226. {
  1227. {"or", or_fn, bad_special2, bad_specialn},
  1228. {"prog", prog_fn, bad_special2, bad_specialn},
  1229. {"prog1", prog1_fn, bad_special2, bad_specialn},
  1230. {"prog2", prog2_fn, bad_special2, bad_specialn},
  1231. /* {"progn", progn_fn, bad_special2, bad_specialn}, */
  1232. /* {"quote", quote_fn, bad_special2, bad_specialn}, */
  1233. {"return", return_fn, bad_special2, bad_specialn},
  1234. {"setq", setq_fn, bad_special2, bad_specialn},
  1235. {"noisy-setq", noisy_setq_fn, bad_special2, bad_specialn},
  1236. {"tagbody", tagbody_fn, bad_special2, bad_specialn},
  1237. {"throw", throw_fn, bad_special2, bad_specialn},
  1238. {"unless", unless_fn, bad_special2, bad_specialn},
  1239. {"unwind-protect", unwind_protect_fn, bad_special2, bad_specialn},
  1240. {"when", when_fn, bad_special2, bad_specialn},
  1241. #ifdef COMMON
  1242. {"macrolet", macrolet_fn, bad_special2, bad_specialn},
  1243. {"multiple-value-call", mv_call_fn, bad_special2, bad_specialn},
  1244. {"multiple-value-prog1", mv_prog1_fn, bad_special2, bad_specialn},
  1245. /*--{"prog*", progstar_fn, bad_special2, bad_specialn}, */
  1246. {"progv", progv_fn, bad_special2, bad_specialn},
  1247. {"return-from", return_from_fn, bad_special2, bad_specialn},
  1248. {"the", the_fn, bad_special2, bad_specialn},
  1249. #else
  1250. {"list", list_fn, bad_special2, bad_specialn},
  1251. {"list*", liststar_fn, bad_special2, bad_specialn},
  1252. {"plus", plus_fn, bad_special2, bad_specialn},
  1253. {"times", times_fn, bad_special2, bad_specialn},
  1254. #endif
  1255. {NULL, 0, 0, 0}};
  1256. /* end of eval3.c */