Add missing semicolon
[maxima.git] / tests / rtest_translator.mac
blob1334f2e18c3f1ac5a9242ef5b423f3519e850e3b
1 /* A nice test of the translator would be to translate the entire test suite ...
2  * In the meantime here are some tests to verify some specific bugs are fixed.
3  */
5 (kill (all), 0);
6 0;
8 /* There are various cases where (by design) translate and compile don't
9  * signal an error when a function fails to translate.  So here we define
10  * translate_or_lose and compile_or_lose so we don't have to explicitly
11  * check the return values of translate and compile in every test.
12  *
13  * Passing `all' or `functions' is not supported.  I'm not sure how much
14  * sense those make here for tests, but something could be added later if
15  * a test really wants them for some reason.
16  */
17 block ([translate : false],
18   local (make_tester),
19   make_tester (trfun) ::=
20     buildq ([trfun, name : concat (trfun, '_or_lose)],
21       (name (['fns]) :=
22          block ([ret : apply ('trfun, fns), losers : []],
23            if ret # fns then
24              /* Report failures in the same order as the given args */
25              (for f in fns do if not (member (f, ret)) then push (f, losers),
26               error ('trfun, "failed unexpectedly for", reverse (losers))),
27            fns),
28        /* Prevent this from being killed during kill(all), etc.
29         * We can remove this later if we're more precise about
30         * what we're killing throughout this file.
31         */
32        ?mfunction\-delete ('name, functions))),
33   make_tester (translate),
34   make_tester (compile),
35   0);
38 /* SF [ 1728888 ] translator bugs: no mnot mprogn */
40 (foo (e,v) := block([vi], for vi in v while not(emptyp(e)) do (print(vi), e : rest(e)), e),
41  foo ([1, 2, 3], [a, b]));
42 [3];
44 (translate_or_lose (foo), foo ([1, 2, 3], [a, b]));
45 [3];
47 /* simpler function featuring mprogn and mnot */
49 (bar (x) := (x : 2*x, x : 3*x, not (x < 100)), bar (3));
50 false;
52 (translate_or_lose (bar), bar (3));
53 false;
55 /* SF [ 1646525 ] no function mdoin */
57 (try_me(x) := block([acc : 0], for i in x while i > 5 do acc : acc + i, acc),
58  try_me ([10, 9, 8, 7, 6, 5, 4, 5, 6, 7, 8, 9, 10]));
59 40;
61 (translate_or_lose (try_me), try_me ([10, 9, 8, 7, 6, 5, 4, 5, 6, 7, 8, 9, 10]));
62 40;
64 /* SF [ 1818645 ] Compiled maxima code containing $ARRAY gets a Lisp error. */
66 (test_array_comp (x) :=
67   block ([abc, i],
68     array (abc, 3),
69     for i thru 3 do (abc[i]: i*i),
70     abc[3] : x, 
71     [abc, abc[3], abc[2]]),
72   test_array_comp (100));
73 [abc, 100, 4];
75 (translate_or_lose (test_array_comp), test_array_comp (100));
76 [abc, 100, 4];
78 /* SF [ 545794 ] Local Array does not compile properly */
80 (trial (a) :=
81   block ([myvar, i],
82     local(myvar),
83     array (myvar, 7),
84     for i : 0 thru 7 do myvar [i] : a^i,
85     [member (myvar, arrays), listarray (myvar)]),
86  trial (2));
87 [true, [1, 2, 4, 8, 16, 32, 64, 128]];
89 (translate_or_lose (trial), trial (2));
90 [true, [1, 2, 4, 8, 16, 32, 64, 128]];
92 /* This next test used to fail because local properties would leak out
93  * in the translated case.  This test is expected to pass now.  There
94  * are more local tests below for bug #2976.
95  */
97 [member (myvar, arrays), errcatch (listarray (myvar))];
98 [false, []];
100 /* for loop variable not special
101  * reported to mailing list 2009-08-13 "Why won't this compile?"
102  */
104 (kill (foo1, bar1),
105  foo1 () := bar1 + 1,
106  baz1 (n) := block ([S : 0], for bar1:0 thru n - 1 do S : S + foo1 (), S),
107  translate_or_lose (baz1),
108  baz1 (10));
111 /* original example */
113 (fun(A,b,s,VF,x,h):= block
114  ([Y],
115    Y[1]:  x,
116    for i:2 thru s do
117     Y[i]:  x + h*(sum(A[i,j]*VF(Y[j]),j,1,i-1)),
118    x: expand(x + h*sum(b[i]*VF(Y[i]),i,1,s))),
119   A: matrix([1,1],[1,1]),
120   b: [1,1],
121  0);
124 fun(A,b,2,f,[1,1],.01);
125 0.01*f(0.01*f([1,1])+[1,1])+0.01*f([1,1])+[1,1]$
127 (translate_or_lose (fun), fun(A,b,2,f,[1,1],.01));
128 0.01*f(0.01*f([1,1])+[1,1])+0.01*f([1,1])+[1,1]$
130 /* incorrect code emitted for call from translated function to untranslated
131  * SF bug # 2934064 "problem loading ezunits"
132  */
134 (f0001 (x) := [f0002 (x), f0003 (x)],
135  f0002 (x) := x,
136  f0003 (x) := x,
137  translate_or_lose (f0002, f0001),
138  f0001 (1));
139 [1, 1];
141 (translate_or_lose (f0003), f0001 (1));
142 [1, 1];
144 (compile_or_lose (f0003), f0001 (1));
145 [1, 1];
147 (compile_or_lose (f0003, f0002, f0001), f0001 (1));
148 [1, 1];
150 /* SF bug # 2938716 "too much evaluation in translated code"
151  */
153 (g0001 (x) := [g0002 (x), g0003 (x)],
154  g0002 (x) := x,
155  g0003 (x) := x,
156  translate_or_lose (g0002, g0001),
157  kill (aa, bb, cc),
158  aa : 'bb,
159  bb : 'cc,
160  g0001 (aa));
161 [bb, bb];
163 (translate_or_lose (g0003), g0001 (aa));
164 [bb, bb];
166 (compile_or_lose (g0003), g0001 (aa));
167 [bb, bb];
169 (compile_or_lose (g0003, g0002, g0001), g0001 (aa));
170 [bb, bb];
172 /* SF bug # 3035313 "some array references translated incorrectly"
173  */
175 (kill (aa1, aa3, bb1, bb3, cc1, cc3),
176  array (aa1, 15),
177  array (aa3, 12, 4, 6),
178  array (bb1, flonum, 15),
179  array (bb3, flonum, 5, 6, 7),
180  array (cc1, fixnum, 8),
181  array (cc3, fixnum, 6, 10, 4),
182  0);
185 (kill (faa, gaa, fbb, gbb, fcc, gcc),
186  faa (n) := aa1[n] + aa3[n, n - 1, n - 2],
187  gaa (n) := (aa1[n] : 123, aa3[n, n - 1, n - 2] : 321),
188  fbb (n) := bb1[n] + bb3[n, n - 1, n - 2],
189  gbb (n) := (bb1[n] : 123, bb3[n, n - 1, n - 2] : 321),
190  fcc (n) := cc1[n] + cc3[n, n - 1, n - 2],
191  gcc (n) := (cc1[n] : 123, cc3[n, n - 1, n - 2] : 321),
192  0);
195 [gaa (4), gbb (4), gcc (4)];
196 [321, 321, 321];
198 [faa (4), fbb (4), fcc (4)];
199 [444, 444, 444];
201 translate_or_lose (faa, gaa, fbb, gbb, fcc, gcc);
202 [faa, gaa, fbb, gbb, fcc, gcc];
204 [gaa (4), gbb (4), gcc (4)];
205 [321, 321, 321];
207 [faa (4), fbb (4), fcc (4)];
208 [444, 444, 444];
210 compile_or_lose (faa, gaa, fbb, gbb, fcc, gcc);
211 [faa, gaa, fbb, gbb, fcc, gcc];
213 [gaa (4), gbb (4), gcc (4)];
214 [321, 321, 321];
216 [faa (4), fbb (4), fcc (4)];
217 [444, 444, 444];
219 /* try same stuff again w/ undeclared arrays ...
220  * no type spec => only one kind of array
221  */
223 (kill (aa1, aa3, bb1, bb3, cc1, cc3),
224  ?fmakunbound (faa),
225  ?fmakunbound (fbb),
226  [gaa (4), faa (4)]);
227 [321, 444];
229 (translate_or_lose (faa, gaa), [gaa (4), faa (4)]);
230 [321, 444];
232 (compile_or_lose (faa, gaa), [gaa (4), faa (4)]);
233 [321, 444];
235 /* try same stuff again w/ Lisp arrays */
237 (kill (aa1, aa3, bb1, bb3, cc1, cc3),
238  map (?fmakunbound, [faa, fbb, fcc, gaa, gbb, gcc]),
239  aa1 : make_array (any, 15),
240  aa3 : make_array (any, 12, 4, 6),
241  bb1 : make_array (flonum, 15),
242  bb3 : make_array (flonum, 5, 6, 7),
243  cc1 : make_array (fixnum, 8),
244  cc3 : make_array (fixnum, 6, 10, 4),
245  0);
248 [gaa (4), gbb (4), gcc (4)];
249 [321, 321, 321];
251 [faa (4), fbb (4), fcc (4)];
252 [444, 444, 444];
254 translate_or_lose (faa, gaa, fbb, gbb, fcc, gcc);
255 [faa, gaa, fbb, gbb, fcc, gcc];
257 [gaa (4), gbb (4), gcc (4)];
258 [321, 321, 321];
260 [faa (4), fbb (4), fcc (4)];
261 [444, 444, 444];
263 compile_or_lose (faa, gaa, fbb, gbb, fcc, gcc);
264 [faa, gaa, fbb, gbb, fcc, gcc];
266 [gaa (4), gbb (4), gcc (4)];
267 [321, 321, 321];
269 [faa (4), fbb (4), fcc (4)];
270 [444, 444, 444];
272 /* SF bug # 2569: "translate rat(1,x) and rat([1]) incorrect" */
274 (kill (f), f () := rat (x, x), translate_or_lose (f), f ());
275 ''(rat (x, x));
277 (kill (f), f () := rat ([1]), translate_or_lose (f), f ());
278 ''(rat ([1]));
280 (kill (foo, y1a, y1b, y2a, y2b), 
281   foo(x) := block (mode_declare (x, float),
282      [tanh (x), tan (x), sech (x), sec (x), acos (x), acot (x), sin (x),
283       acsc (x), asinh (x), acsch (x), cosh (x), coth (x), realpart (x),
284       asec (x), asin (x), erf (x), log (x), plog (x), cos (x), cot (x), csc (x),
285       sinh (x), csch (x), sqrt (x), exp (x), atan2 (11, x), atan2 (x, 2/3)]),
286   0);
289 y1a : foo (0.5);
290 [.4621171572600097,.5463024898437905,0.886818883970074,1.139493927324549,
291  1.047197551196597,1.107148717794091,0.479425538604203,
292  1.570796326794897-1.316957896924817*%i,.4812118250596035,1.44363547517881,
293  1.127625965206381,2.163953413738653,0.5,1.316957896924817*%i,
294  0.523598775598299,.5204998778130465,-.6931471805599453,-.6931471805599453,
295  .8775825618903728,1.830487721712452,2.085829642933488,.5210953054937474,
296  1.919034751334944,.7071067811865476,1.648721270700128,1.5253730473733196,
297  0.6435011087932844]$
299 y1b : foo (1.5);
300 [.9051482536448664,14.10141994717172,.4250960349422805,14.1368329029699,
301  .9624236501192069*%i,.5880026035475675,.9974949866040544,.7297276562269662,
302  1.194763217287109,.6251451172504168,2.352409615243247,1.104791392982512,1.5,
303  .8410686705679303,1.570796326794897-.9624236501192069*%i,.9661051464753108,
304  .4054651081081644,.4054651081081644,0.0707372016677029,.07091484430265245,
305  1.002511304246725,2.129279455094817,.4696424405952246,1.224744871391589,
306  4.481689070338065,1.4352686128093959,1.1525719972156676]$
308 y1c : foo (1.0);
309 [0.7615941559557649,1.557407724654902,0.6480542736638855,
310  1.850815717680925,0.0,0.7853981633974483,0.8414709848078965,
311  1.570796326794897,0.881373587019543,0.881373587019543,
312  1.543080634815244,1.313035285499331,1.0,0.0,1.570796326794897,
313  0.8427007929497148,0.0,0.0,0.5403023058681398,0.6420926159343306,
314  1.188395105778121,1.175201193643801,0.8509181282393216,1.0,
315  2.718281828459045,1.4801364395941514,0.982793723247329]$
317 (translate_or_lose (foo), y2a : foo (0.5), y2b : foo (1.5), 0);
320 is (y1a = y2a);
321 true;
323 is (y1b = y2b);
324 true;
326 block ([tr_float_can_branch_complex : false],
327   translate_or_lose (foo),
328   y2c : foo (1.0),
329   0);
332 is (y1c = y2c);
333 true;
335 /* verify that save/compfile/compile_file/translate_file preserves upper/lower case in symbol names */
337 /* save */
339 (kill (all),
340  foo (x) := my_foo * x,
341  Foo (x) := my_Foo * x,
342  FOO (x) := my_FOO * x,
343  [my_foo, my_Foo, my_FOO] : [123, 456, 789],
344  results : [foo (2), Foo (3), FOO (4)],
345  my_test () := is (results = [2*123, 3*456, 4*789]),
346  lisp_name : ssubst ("_", " ", build_info()@lisp_name),
347  lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-save-", lisp_name, ".lisp"),
348  save (lisp_filename, values, functions),
349  kill (allbut (lisp_filename)),
350  load (lisp_filename),
351  my_test ());
352 true;
354 /* compfile */
356 (kill (all),
357  foo (x) := my_foo * x,
358  Foo (x) := my_Foo * x,
359  FOO (x) := my_FOO * x,
360  lisp_name : ssubst ("_", " ", build_info()@lisp_name),
361  lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compfile-", lisp_name, ".lisp"),
362  compfile (lisp_filename, functions),
363  kill (functions), 
364  load (lisp_filename),
365  [my_foo, my_Foo, my_FOO] : [123, 456, 789],
366  results : [foo (2), Foo (3), FOO (4)],
367  my_test () := is (results = [2*123, 3*456, 4*789]),
368  my_test ());
369 true;
371 /* compile_file */
373 /* skip this test (and fail) if Lisp = ECL because stream i/o causes "stack smashing" error
374  * see: https://sourceforge.net/p/maxima/bugs/3291/
375  */
376 if build_info()@lisp_name # "ECL" then
377 (kill (all),
378  lisp_name : ssubst ("_", " ", build_info()@lisp_name),
379  maxima_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compile_file-", lisp_name, ".mac"),
380  fasl_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compile_file-", lisp_name, ".fasl"),
381  lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compile_file-", lisp_name, ".LISP"),
382  maxima_output : openw (maxima_filename),
383  maxima_content :
384 "foo (x) := my_foo * x;
385 Foo (x) := my_Foo * x;
386 FOO (x) := my_FOO * x;
387 [my_foo, my_Foo, my_FOO] : [123, 456, 789];
388 results : [foo (2), Foo (3), FOO (4)];
389 my_test () := is (results = [2*123, 3*456, 4*789]);",
390  printf (maxima_output, maxima_content),
391  close (maxima_output),
392  compile_file (maxima_filename, fasl_filename, lisp_filename),
393  kill (allbut (lisp_filename)),
394  load (lisp_filename),
395  my_test ());
396 true;
398 /* translate_file */
400 /* skip this test (and fail) if Lisp = ECL because stream i/o causes "stack smashing" error
401  * see: https://sourceforge.net/p/maxima/bugs/3291/
402  */
403 if build_info()@lisp_name # "ECL" then
404 (kill (all),
405  lisp_name : ssubst ("_", " ", build_info()@lisp_name),
406  maxima_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-translate_file-", lisp_name, ".mac"),
407  lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-translate_file-", lisp_name, ".LISP"),
408  maxima_output : openw (maxima_filename),
409  maxima_content :
410 "foo (x) := my_foo * x;
411 Foo (x) := my_Foo * x;
412 FOO (x) := my_FOO * x;
413 [my_foo, my_Foo, my_FOO] : [123, 456, 789];
414 results : [foo (2), Foo (3), FOO (4)];
415 my_test () := is (results = [2*123, 3*456, 4*789]);",
416  printf (maxima_output, maxima_content),
417  close (maxima_output),
418  translate_file (maxima_filename, lisp_filename),
419  kill (allbut (lisp_filename)),
420  load (lisp_filename),
421  my_test ());
422 true;
424 /* Bug 2934:
426    Translating a literal exponent that comes out as a float shouldn't
427    produce assigned type any. This test runs the translation for a
428    trivial function that triggered the bug then looks in the unlisp
429    file (which contains messages from the translator) and checks that
430    there aren't any warnings.
432 /* skip this test (and fail) if Lisp = ECL because stream i/o causes "stack smashing" error
433  * see: https://sourceforge.net/p/maxima/bugs/3291/
434  */
435 if build_info()@lisp_name # "ECL" then
436 (kill (all),
437  lisp_name : ssubst ("_", " ", build_info()@lisp_name),
438  basename: sconcat (maxima_tempdir, "/tmp-rtest_translator-2934-", lisp_name),
439  maxima_filename : sconcat (basename, ".mac"),
440  lisp_filename : sconcat (basename, ".LISP"),
441  maxima_output : openw (maxima_filename),
442  maxima_content : "f () := block([y], mode_declare(y,float), y: 3^0.33, y)$",
443  printf (maxima_output, maxima_content),
444  close (maxima_output),
445  translate_file (maxima_filename, lisp_filename),
446  kill (allbut(basename)),
447  /* Any warning messages end up at .UNLISP */
448  block ([unlisp: openr (sconcat (basename, ".UNLISP")),
449          line, acc: []],
450    while stringp (line: readline(unlisp)) do
451      if is ("warning" = split(line, ":")[1]) then push(line, acc),
452    acc));
455 /* makelist translated incorrectly
456  * SF bug #3083: "Error on compiling a working maxima function"
457  */
459 (kill(all),
460  f1(n) := makelist (1, n),
461  f2(n) := makelist (i^2, i, n),
462  f3(l) := makelist (i^3, i, l),
463  f4(n) := makelist (i^4, i, 1, n),
464  f5(m, n) := makelist (i^5, i, 1, n, m),
465  translate_or_lose(f1, f2, f3, f4, f5),
466  0);
469 f1(5);
470 [1,1,1,1,1];
472 f2(5);
473 [1, 4, 9, 16, 25];
475 f3([1,2,3]);
476 [1, 8, 27];
478 f4(4);
479 [1, 16, 81, 256];
481 f5(2, 10);
482 [1, 243, 3125, 16807, 59049];
484 /* original function from bug report */
486 (ordersort(lis,vars,oper):=block([negsumdispflag:false,liss:lis,varlist:vars,temp], /*Does lexicographical sort */
487  for i:1 thru length(varlist) do (
488      for j:1 thru i do (
489          liss:sort(liss,lambda([x,y],apply("and",map(oper,makelist(part(x,2)[k],k,1,i)
490                              ,makelist(part(y,2)[k],k,1,i)))))
491      )),liss),
492  translate_or_lose (ordersort),
493  [member ('transfun, properties (ordersort)),
494   ordersort([[-7,[0,2,1]],[3,[1,2,1]],[1,[0,4,1]],[6,[4,3,3]],[6,[4,4,3]],
495              [-7,[3,5,4]],[2,[0,0,5]],[-10,[2,2,5]],[-10,[3,4,7]],[7,[3,8,9]]],
496              [x,y,z],
497              ">=")]);
498 [true,
499  [[6,[4,4,3]],[6,[4,3,3]],[7,[3,8,9]],[-7,[3,5,4]],[-10,[3,4,7]],
500   [-10,[2,2,5]],[3,[1,2,1]],[1,[0,4,1]],[-7,[0,2,1]],[2,[0,0,5]]]];
502 /* 'define' translated incorrectly, reported to mailing list circa 2017-01-24 */
504 (kill(foo, bar, baz, quux, mumble, blurf, umm, f, x, y),
505  foo(y) := define(bar(x), x + y),
506  baz(f, y) := define(funmake(f, [x]), x + y),
507  quux() := (mumble(x) := 1 + x),
508  [foo(10), baz(blurf, 20), quux()]);
509 /* note that results match because rhs of ":=" isn't simplified */
510 [bar(x) := 10 + x, blurf(x) := 20 + x, mumble(x) := 1 + x];
512 [bar(5), blurf(5), mumble(5)];
513 [15, 25, 6];
515 (kill(bar, blurf, mumble),
516  translate_or_lose(foo, baz, quux),
517  [foo(11), baz(umm, 21), quux()]);
518 /* note that results match because rhs of ":=" isn't simplified */
519 [bar(x) := 11 + x, umm(x) := 21 + x, mumble(x) := 1 + x];
521 makelist (is (x # false), x, map (?fboundp, [foo, baz, quux])); /* test for generalized Boolean value */
522 [true, true, true];
524 [bar(5), umm(5), mumble(5)];
525 [16, 26, 6];
527 /* mailing list 2017-03-04: "An example that is broken by compile()"
528  * translated code tickles a bug elsewhere (bug not in translator)
529  */
531 (kill(fun, trigfunc, t1),
532  fun():=block([trigfunc],
533         trigfunc:lambda([cur],cur>t1),
534         apply('trigfunc,[1])),
535  0);
538 /* I (Robert Dodier) believe this result should be trigfunc(1),
539  * but, in any event, interpreted and compiled code should agree.
540  * But if MAPPLY1 is ever changed, we can adjust these results.
541  */
542 fun();
543 1 > t1;
545 (compile_or_lose(fun), fun());
546 1 > t1;
548 (kill(fun, trigfunc, t1),
549  fun():=block([trigfunc],
550         trigfunc:lambda([cur],cur>t1),
551         apply(trigfunc,[1])),
552  0);
555 fun();
556 1 > t1;
558 (compile_or_lose(fun), fun());
559 1 > t1;
561 /* Verify that we catch malformed lambda expressions during translation.
562  * More checks need to be added to the translator and more tests need to
563  * be added here.
564  */
566 /* no parameter list */
567 (kill (f),
568  f () := lambda (),
569  translate (f))$
572 /* empty body */
573 (kill (f),
574  f () := lambda ([x]),
575  translate (f))$
578 /* non-symbol in parameter list */
579 (kill (f),
580  f () := lambda ([42], 'foo),
581  translate (f))$
584 /* misplaced "rest" parameter */
585 (kill (f),
586  f () := lambda ([[l], x], 'foo),
587  translate (f))$
590 /* invalid "rest" parameter */
591 (kill (f),
592  f () := lambda ([[l1, l2]], 'foo),
593  translate (f))$
596 /* attempting to bind a constant;
597  * now OK, after commit 0517895
598  */
599 block ([c, f],
600   local (c, f),
601   declare (c, constant),
602   f () := lambda ([c], c),
603   translate_or_lose (f))$
604 [f];
606 /* Verify that parameter/variable lists cannot contain duplicate variables.
608  * We only test a couple of cases here.  Many more tests for non-translated
609  * code are in rtest2.  Do we want to test them all here as well?
610  */
612 (kill(f),
613  f () := lambda ([x, [x]], x),
614  translate (f))$
617 (kill(f),
618  f () := block ([x, x:'foo], x),
619  translate (f))$
622 /* ensure that a null OPERATORS property doesn't interfere with
623  * translation of local variable used as a function name.
624  * This is the bug that caused failures in rtest_fractals when executed after run_testsuite.
625  */
627 (kill(aa, foobarbaz, mumbleblurf, hhh),
628  matchdeclare (aa, all),
629  tellsimp (mumbleblurf(aa), 1 - aa),
630  kill (mumbleblurf), /* as of 2018-01-28, this leaves (OPERATORS NIL) in property list */
631  hhh(mumbleblurf, u) := mumbleblurf(u),
632  foobarbaz(x) := 100 + x,
633  translate_or_lose (hhh),
634  hhh (foobarbaz, 11));
635 111;
637 /* SF bug report #3402: "Unbinding defined variable generates error in compiled functions" */
639 define_variable (zorble, 0, fixnum);
642 (kill(f), f() := block ([zorble], 42), f());
645 (translate_or_lose(f), f());
648 /* bug reported to mailing list 2018-12-03: "error in compiling function with global variable" */
650 (test_f():= block( [a,b,c,d], niceindicespref:[a,b,c,d], disp("ciao"), return() ),
651  0);
654 (test_f (), niceindicespref);
655 [a,b,c,d];
657 (reset (niceindicespref),
658  niceindicespref);
659 [i,j,k,l,m,n];
661 (translate_or_lose (test_f),
662  test_f (),
663  niceindicespref);
664 [a,b,c,d];
666 (reset (niceindicespref), 0);
669 /* additional tests with variables which have ASSIGN property */
671 (set_error_stuff_permanently () :=
672   block (error_syms : '[myerr1, myerr2, myerr3], error_size : 40),
673  set_error_stuff_temporarily() :=
674    block([error_syms : '[myerror1, myerror2, myerror3], error_size : 55],
675          [error_syms, error_size]),
676  0);
679 (reset (error_syms, error_size),
680  set_error_stuff_permanently (),
681  [error_syms, error_size]);
682 [[myerr1, myerr2, myerr3], 40];
684 (reset (error_syms, error_size),
685  translate_or_lose (set_error_stuff_permanently),
686  set_error_stuff_permanently (),
687  [error_syms, error_size]);
688 [[myerr1, myerr2, myerr3], 40];
690 (reset (error_syms, error_size),
691  set_error_stuff_temporarily());
692 [[myerror1, myerror2, myerror3], 55];
694 [error_syms, error_size];
695 [[errexp1, errexp2, errexp3], 60];
697 (translate_or_lose (set_error_stuff_temporarily),
698  set_error_stuff_temporarily());
699 [[myerror1, myerror2, myerror3], 55];
701 [error_syms, error_size];
702 [[errexp1, errexp2, errexp3], 60];
704 (kill(all), reset(), 0);
707 /* SF bug #3412: "Bug when translating functions that contain an \"if\" (in my case an implicit if)" */
708 /* Bug #4008: translator and prederror */
710 (f(x):=if cabs(1/(x+1)) < 1 then 1/(x+1) else 1,
711  f(x + %i*y));
712 if 1/sqrt(y^2+(x+1)^2) < 1 then 1/(%i*y+x+1) else 1;
714 makelist (f(xy[1] + %i*xy[2]), xy, [[0, 0], [0, 1], [1, 1], [1, 0], [0, 2], [2, 2], [2, 0]]);
715 [1, 1/(%i+1), 1/(%i+2), 1/2, 1/(2*%i+1), 1/(2*%i+3), 1/3]$
717 compile_or_lose (f);
718 [f];
720 block ([prederror : false],
721   f(x + %i*y));
722 if 1 - 1/sqrt(y^2+(x+1)^2) > 0 then 1/(%i*y+x+1) else 1;
724 block ([prederror : true],
725   errcatch (f(x + %i*y)));
728 '(f(x + %i*y));
729 f(x + %i*y);
731 makelist (f(xy[1] + %i*xy[2]), xy, [[0, 0], [0, 1], [1, 1], [1, 0], [0, 2], [2, 2], [2, 0]]);
732 [1, 1/(%i+1), 1/(%i+2), 1/2, 1/(2*%i+1), 1/(2*%i+3), 1/3]$
734 (if draw_version = 'draw_version then load (draw),
735  draw3d(contour='map,
736         proportional_axes=xy,
737         nticks=100,
738         contour_levels=20,
739         explicit('(f(x+%i*y)),x,-2,2,y,-2,2)),
740  0);
743 /* nested if example -- note top-level "if" doesn't have an "else" clause, so the result is sometimes 'false' */
745 (g(a, b, c) := if a + b > c
746                  then (if a > c
747                          then (if b > c
748                                  then (a + b + c)
749                                  elseif b > c/2
750                                    then (a - b - c)
751                                    else (b - a - c))
752                          else (a/2)),
753  0);
756 (aa: [3,9/4,5/4,11/4,1,0,9/4,1/4,5/2,9/4,3,5/2],
757  bb: [3/2,3,1/4,3/4,5/2,7/4,5/2,3/4,1/2,3,13/4,7/2],
758  cc: [7/2,15/4,5/2,5/4,15/4,1,1/4,7/4,2,11/4,1/4,7/4],
759  map (g, aa, bb, cc));
760 [3/2,9/8,false,3/4,false,0,5,false,-4,9/8,13/2,31/4]$
762 (translate_or_lose (g),
763  map (g, aa, bb, cc));
764 [3/2,9/8,false,3/4,false,0,5,false,-4,9/8,13/2,31/4]$
766 block ([prederror : false],
767   g (1, 1, z));
768 ''(if 2 - z > 0 then (if 1 > z then (if 1 > z then z + 2 elseif 1 > z / 2 then -z else -z) else 1/2));
770 block ([prederror : true],
771   errcatch (g (1, 1, z)));
774 /* SF bug #3556: "5.43.0 translate / compile error"
775  * Ensure that "if" within lambda is translated correctly.
776  * The fix for #3412 tickled this bug.
777  */
779 (kill (f),
780  f(x, m) := map (lambda ([u], if m > 0 then u^m), [x, 2*x, 3*x]),
781  0);
784 is (?fboundp (f) # false);
785 false;
787 (kill (y),
788  [f(y, 2), f(y, -2)]);
789 [[y^2, 4*y^2, 9*y^2], [false, false, false]];
791 (kill (n),
792  errcatch (f(10, n)));
793 /* ensure that conditional expressions get simplified to expunge $FALSE ... sigh. */
794 ''([[if n > 0 then 10^n, if n > 0 then 20^n, if n > 0 then 30^n]]);
796 (translate_or_lose (f),
797  is (?fboundp (f) # false)); /* test for generalized Boolean value */
798 true;
800 [f(y, 2), f(y, -2)];
801 [[y^2, 4*y^2, 9*y^2], [false, false, false]];
803 block ([prederror : false],
804   f(10, n));
805 ''([if n > 0 then 10^n, if n > 0 then 20^n, if n > 0 then 30^n]);
807 block ([prederror : true],
808   errcatch (f(10, n)));
811 /* apply2 was translated incorrectly for several years.  applyb2
812  * was translated incorrectly for decades.
813  */
815 (defrule (foorule, foo (), 1),
816  f () := apply2 ('(foo ()), foorule),
817  translate_or_lose (f),
818  f ());
821 (defrule (barrule, bar (), 2),
822  g () := applyb2 ('(bar ()), barrule),
823  translate_or_lose (g),
824  g ());
827 (kill (foorule, f, barrule, g), 0);
830 /* atan and atan2 calls with float arguments were translated
831  * incorrectly for over a decade.  atan always caused a lisp error
832  * and atan2 had a range between 0 and 2*%pi that was inconsistent
833  * with the interpreted and non-float cases (where the range is
834  * between -%pi and %pi).
835  */
837 (foo () := [atan2 (-1.0, -1.0), atan2 (-1.0, 1.0)],
838  translate_or_lose (foo),
839  foo ());
840 [-2.356194490192345, -0.7853981633974483];
842 (bar () := atan (-1.0),
843  translate_or_lose (bar),
844  bar ());
845 -0.7853981633974483;
847 (kill (foo, bar), 0);
850 /* The translation of a signum call with a float argument was
851  * inconsistent when compared to the interpreted case and other
852  * translated cases.  signum should return an integer or a float
853  * when given an integer or a float argument, respectively.
854  */
856 (foo () := [signum (0),  signum (0.0),
857             signum (2),  signum (2.0),
858             signum (-3), signum (-3.0)],
859  translate_or_lose (foo),
860  foo ());
861 [0, 0.0, 1, 1.0, -1, -1.0];
863 (kill (foo), 0);
866 /* The translation of declare was broken for decades.  It worked
867  * under Maclisp, but it had never worked under Common Lisp.
868  */
870 (foo () := declare (n, integer, [x, y], noninteger),
871  translate_or_lose (foo),
872  foo (),
873  [?kindp (n, integer),
874   ?kindp (n, noninteger),
875   ?kindp (x, integer),
876   ?kindp (x, noninteger),
877   ?kindp (y, integer),
878   ?kindp (y, noninteger)]);
879 [true, false, false, true, false, true];
881 (kill (foo, n, x, y), 0);
884 /* If a variable was declared to be of mode rational, then a lisp
885  * error could occur during translation when attempting to convert
886  * it to a float.
887  */
889 (foo (x) := (mode_declare (x, rational), float (x)),
890  bar (y) := (mode_declare (y, rational), 1.0 + y),
891  translate_or_lose (foo, bar),
892  [foo (1/4), bar (1/2)]);
893 [0.25, 1.5];
895 (kill (foo, bar, x, y), 0);
898 /* The translation of an atan2 call with one float and one rational
899  * argument was broken because the rational was not converted to a
900  * float before calling ATAN.
901  */
903 (foo () :=
904    [atan2 (0.0, -1/2),
905     atan2 (-1/2, 0.0),
906     atan2 (0.0, -1),
907     atan2 (1, 0.0)],
908  bar (y, x) := (mode_declare (x, float, y, rational), atan2 (y, x)),
909  l1 : [foo (), bar (1/3, 0.0)],
910  translate_or_lose (foo, bar),
911  l2 : [foo (), bar (1/3, 0.0)],
912  is (l1 = l2));
913 true;
915 (kill (foo, bar, x, y, l1, l2), 0);
918 /* When attempting to apply float contagion to the arguments, some
919  * translations of max and min with mixed float and rational arguments
920  * were broken because the rationals were not converted to floats before
921  * calling MAX or MIN (like atan2 above).  Also, due to implementation-
922  * dependent behavior in the underlying lisp regarding what to return
923  * from MAX and MIN, the wrong mode could be used during translation and
924  * some of the translations were possibly inconsistent with interpreted
925  * cases.
926  */
928 (foo (x) :=
929    (mode_declare (x, rational),
930     [max (),         min (),
931      max (1),        min (1),
932      max (1.0),      min (1.0),
933      max (9/10),     min (9/10),
934      max (x)   ,     min (x),
935      max (0.0, 1),   min (0.0, 1),
936      max (0, 1),     min (0, 1),
937      max (1.0, 1),   min (1.0, 1),
938      max (1, 1.0),   min (1, 1.0),
939      max (2.0, 3.0), min (2.0, 3.0),
940      max (-1, 1/2),  min (-1, 1/2),
941      max (3/4, 1/2), min (3/4, 1/2),
942      max (0.0, 1/2), min (0.0, 1/2),
943      max (0, x),     min (0, x),
944      max (-1.0, x),  min (-1.0, x),
945      max (5/6, x),   min (5/6, x),
946      max (x, 1),     min (x, 1)]),
947  l1 : foo (2/3),
948  translate_or_lose (foo),
949  l2 : foo (2/3),
950  is (l1 = l2));
951 true;
953 (kill (foo, x, l1, l2), 0);
956 /* log and sqrt did not honor tr_float_can_branch_complex */
958 (foo (x) :=
959    (mode_declare (x, float),
960     [log  (-1.0), log  (x),
961      sqrt (-1.0), sqrt (x)]),
962  /* l1 is a list of Maxima complex numbers */
963  l1 : foo (-2.0),
964  some (lambda ([x], freeof (%i, x)), l1));
965 false;
967 block ([tr_float_can_branch_complex : false],
968   translate_or_lose (foo),
969   /* l2 is a list of lisp complex numbers because we told the
970    * translator to assume the return values of log and sqrt
971    * would not be complex, and it correctly returned the complex
972    * numbers returned by LOG and SQRT directly.
973    */
974   l2 : foo (-2.0),
975   [every (?complexp, l2),
976    every ("#", l1, l2)]);
977 [true,
978  true];
980 block ([tr_float_can_branch_complex : true],
981   translate_or_lose (foo),
982   /* l3 is a list of Maxima complex numbers because we told the
983    * translator to assume the return values of log and sqrt
984    * could be complex, and it converted the lisp complex numbers
985    * returned by LOG and SQRT to Maxima complex numbers.
986    */
987   l3 : foo (-2.0),
988   every (lambda ([x, y], cabs (x - y) < 1e-15), l1, l3));
989 true;
991 (kill (foo, x, l1, l2, l3), 0);
994 /* The translations for evaluating = and # expressions to boolean
995  * values with one float argument and a different numerical argument
996  * (e.g. a fixnum) gave bogus results because the translator was
997  * incorrectly applying float contagion to the arguments.
998  */
1000 (foo (s, w, x, y, z) :=
1001   (mode_declare (w, number, x, fixnum, y, flonum),
1002    [/* These translate to EQL comparisons */
1003     is (1 = 1),                 is (1 # 1),
1004     is (1 = 1.0),               is (1 # 1.0),
1005     is (1 = float (1)),         is (1 # float (1)),
1006     is (1.0 = float (1)),       is (1.0 # float (1)),
1007     is (w = 2),                 is (w # 2),
1008     is (w = 2.0),               is (w # 2.0),
1009     is (x = 3),                 is (x # 3),
1010     is (x = 3.0),               is (x # 3.0),
1011     is (x = float (3)),         is (x # float (3)),
1012     is (x = float (x)),         is (x # float (x)),
1013     is (y = 4),                 is (y # 4),
1014     is (y = 4.0),               is (y # 4.0),
1015     is (y = float (4)),         is (y # float (4)),
1016     is (y = float (y)),         is (y # float (y)),
1017     /* These translate to LIKE comparisons */
1018     is (z = 5),                 is (z # 5),
1019     is (z = 5.0),               is (z # 5.0),
1020     is (z = float (5)),         is (z # float (5)),
1021     is (z = float (z)),         is (z # float (z)),
1022     is (1/2 = 1/2),             is (1/2 # 1/2),
1023     is (1/2 = rat (1/2)),       is (1/2 # rat (1/2)),
1024     is (rat (1/2) = rat (1/2)), is (rat (1/2) # rat (1/2)),
1025     is (1/2 = 0.5),             is (1/2 # 0.5),
1026     is (1/2 = float (1/2)),     is (1/2 # float (1/2)),
1027     is (%i = %i),               is (%i # %i),
1028     is (1 + %i = 1 + %i),       is (1 + %i # 1 + %i),
1029     is (s = s),                 is (s # s),
1030     is (s = 'bar),              is (s # 'bar),
1031     is (s = 1),                 is (s # 1),
1032     is (s = 1.0),               is (s # 1.0),
1033     is (s = 1/2),               is (s # 1/2),
1034     is ('f (0) = 'f (0)),       is ('f (0) # 'f (0)),
1035     is ('g (s) = 'g (s)),       is ('g (s) # 'g (s)),
1036     is ('h (w) = 'h (w)),       is ('h (w) # 'h (w)),
1037     is ('i (x) = 'i (x)),       is ('i (x) # 'i (x)),
1038     is ('j (y) = 'j (y)),       is ('j (y) # 'j (y)),
1039     is ('k (z) = 'k (z)),       is ('k (z) # 'k (z))]),
1040  l1 : foo ('bar, 2, 3, 4.0, 5),
1041  translate_or_lose (foo),
1042  l2 : foo ('bar, 2, 3, 4.0, 5),
1043  [every (lambda ([x], ?typep (x, ?boolean)), l2),
1044   is (l1 = l2)]);
1045 [true,
1046  true];
1048 (kill (foo, w, x, y, l1, l2), 0);
1051 /* Bug #3048: notequal is not translated properly
1053  * notequal expressions were only generically translated like user
1054  * function calls and the use of notequal in translated code caused
1055  * a runtime warning about it being totally undefined.  Also the
1056  * evaluation of notequal expressions to boolean values (via is, if,
1057  * etc.) were translated like the evaluation of an unknown predicate.
1058  */
1060 (assume (equal (a, b), notequal (c, d)),
1061  foo () :=
1062   [is (equal (1, 1)),
1063    is (notequal (1, 1)),
1064    is (equal (1, 1.0)),
1065    is (notequal (1, 1.0)),
1066    is (equal (1, 1.0b0)),
1067    is (notequal (1, 1.0b0)),
1068    is (equal (1/2, 0.5)),
1069    is (notequal (1/2, 0.5)),
1070    is (equal (1/2, 0.5b0)),
1071    is (notequal (1/2, 0.5b0)),
1072    is (equal (1, 2)),
1073    is (notequal (1, 2)),
1074    is (equal ('ind, 'ind)),
1075    is (notequal ('ind, 'ind)),
1076    is (equal ('und, 'und)),
1077    is (notequal ('und, 'und)),
1078    is (equal ('a, 'b)),
1079    is (notequal ('a, 'b)),
1080    is (equal ('c, 'd)),
1081    is (notequal ('c, 'd)),
1082    is (equal (x^2 - 1, (x + 1) * (x - 1))),
1083    is (notequal (x^2 - 1, (x + 1) * (x - 1)))],
1084  l1 : foo (),
1085  translate_or_lose (foo),
1086  l2 : foo (),
1087  [every (lambda ([x], ?typep (x, ?boolean)), l2),
1088   is (l1 = l2)]);
1089 [true,
1090  true];
1092 (kill (foo, l1, l2),
1093  forget (equal (a, b), notequal (c, d)),
1094  0);
1097 /* The translation of a call to random with a float argument could
1098  * cause the generation of bogus code because this always had the
1099  * mode of fixnum.
1100  */
1102 (foo (w, x, y, z) :=
1103   (mode_declare (w, fixnum, x, float),
1104    [[random (10),
1105      random (w),
1106      random (y)],
1107     [random (1.0),
1108      random (x),
1109      random (z),
1110      random (x) / 2,
1111      random (z) / 2,
1112      1 / (1 + random (x))],
1113     [random (10) / 2,
1114      random (w) / 3,
1115      random (y) / 4,
1116      1 / (1 + random (w)),
1117      1 / (1 + random (y))]]),
1118  translate_or_lose (foo),
1119  l : foo (50, 5.0, 100, 10.0),
1120  [every (integerp, first (l)),
1121   every (floatnump, second (l)),
1122   every (ratnump, third (l))]);
1123 [true,
1124  true,
1125  true];
1127 (kill (foo, w, x, l), 0);
1130 /* acosh, asech, atanh and acoth now have special translations for
1131  * float arguments.  These all honor tr_float_can_branch_complex.
1132  */
1134 (foo (x) :=
1135    (mode_declare (x, float),
1136     [acosh (x), asech (x), atanh (x)]),
1137  bar (x) :=
1138    (mode_declare (x, float),
1139     [acoth (x)]),
1140  /* l1 is a list of Maxima complex numbers */
1141  l1 : append (foo (-3.0), foo (-2.0), bar (-0.5), bar (0.5)),
1142  some (lambda ([x], freeof (%i, x)), l1));
1143 false;
1145 block ([tr_float_can_branch_complex : false],
1146   translate_or_lose (foo, bar),
1147   /* l2 is a list of lisp complex numbers because we told the
1148    * translator to assume the return values would not be complex,
1149    * and it correctly returned the lisp complex numbers directly.
1150    */
1151   l2 : append (foo (-3.0), foo (-2.0), bar (-0.5), bar (0.5)),
1152   [every (?complexp, l2),
1153    every ("#", l1, l2),
1154    every ("=", l1, map (?complexify, l2))]);
1155 [true,
1156  true,
1157  true];
1159 block ([tr_float_can_branch_complex : true],
1160   translate_or_lose (foo, bar),
1161   /* l3 is a list of Maxima complex numbers because we told the
1162    * translator to assume the return values could be complex, and
1163    * it converted the lisp complex numbers to Maxima complex numbers.
1164    */
1165   l3 : append (foo (-3.0), foo (-2.0), bar (-0.5), bar (0.5)),
1166   every ("=", l1, l3));
1167 true;
1169 (kill (foo, bar, x, l1, l2, l3), 0);
1172 /* Bug #3642: Lisp error when translating assume
1174  * Translating an assume call with an atomic argument would cause a
1175  * lisp error during translation.
1176  */
1178 (foo () :=
1179    block ([ctx : supcontext (),
1180            x : a > 0,
1181            y : b > 0,
1182            r],
1183      assume (x, y, equal (c, 0)),
1184      r : [is (a > 0), is (b < 0), is (equal (c, 0))],
1185      killcontext (ctx),
1186      r),
1187  translate_or_lose (foo),
1188  foo ());
1189 [true, false, true];
1191 (kill (foo), 0);
1194 /* The translation of errcatch was broken because the mode of the
1195  * whole form was always assumed to be the same as the mode of the
1196  * last subform.  Since errcatch always yields a list, lisp errors
1197  * could easily occur.
1198  */
1200 (foo () :=
1201    block ([listarith : true],
1202      [errcatch (1),
1203       1 + errcatch (2),
1204       1.0 * errcatch (2.0),
1205       errcatch (error ("oops")),
1206       errcatch (?error ("oops")),
1207       errcatch (1 / 0)]),
1208  translate_or_lose (foo),
1209  foo ());
1210 [[1],
1211  [3],
1212  [2.0],
1213  [],
1214  [],
1215  []];
1217 (kill (foo), 0);
1220 /* Attempting to translate multiple functions containing local would
1221  * cause an error.  Similarly, translating the same function multiple
1222  * times would cause an error if that function contained local.
1223  */
1225 (foo () := local (), /* just something with local (not within a block) */
1226  bar () := local (), /* something else with local (not within a block) */
1227  translate_or_lose (foo),
1228  translate_or_lose (bar),
1229  translate_or_lose (foo, bar));
1230 [foo, bar];
1232 (kill (foo, bar), 0);
1235 /* Bug #2976: "local" doesn't work in translated code
1237  * For decades no attempt was being made to clean up any local
1238  * properties.
1239  */
1241 /* The internal LOCLIST used by local should be empty right now */
1242 ?null (?loclist);
1243 true;
1245 (f0 () := "one",
1246  foo1 () :=
1247    (local (f0),
1248     f0 () := "two",
1249     f0 ()),
1250  translate_or_lose (foo1),
1251  block ([v : foo1 ()],
1252    [f0 (), v]));
1253 ["one", "two"];
1255 (kill (f0, foo1), 0);
1258 (arr1 [0] : "three",
1259  foo2 () :=
1260    block ([g : lambda ([],
1261                  local (arr1, arr2),
1262                  arr1 [0] : "four",
1263                  arr2 [5] : "five",
1264                  [arr1 [0],
1265                   arr2 [5],
1266                   arrayinfo (arr2)])],
1267      apply (g, [])),
1268  translate_or_lose (foo2),
1269  block ([v : foo2 ()],
1270    [arr1 [0],
1271     v,
1272     errcatch (arrayinfo (arr2))]));
1273 ["three",
1274  ["four",
1275   "five",
1276   [hashed, 1, [5]]],
1277  []];
1279 (kill (arr1, foo2), 0);
1282 (foo3 (n) :=
1283    (local (h),
1284     h () := n + 1,
1285     if n = 10 then
1286       n
1287     else
1288       foo3 (h ())),
1289  translate_or_lose (foo3),
1290  foo3 (0));
1293 (kill (foo3), 0);
1296 /* The internal LOCLIST used by local should be empty right now */
1297 ?null (?loclist);
1298 true;
1300 /* The fpprintprec itself is not important in this test.  I'm
1301  * just picking something that has an ASSIGN property because
1302  * that's a separate internal case in the translator.
1304  * This test is ugly, but it's testing different cases and
1305  * their interactions.
1306  */
1307 block ([v],
1308   local (f1, f2, arr),
1309   f1 () := 0,
1310   f2 () := 123,
1311   arr [1] : "a",
1312   bar (fpprintprec) :=
1313     (local (f1, arr),
1314      fpprintprec : 5,
1315      f1 () := 42,
1316      arr [1] : "b",
1317      [block (
1318         local (f2, arr),
1319         f2 () := 69,
1320         arr [1] : "c",
1321         [f1 (), f2 (), arr [1]]),
1322       [f1 (), f2 (), arr [1]]]),
1323   translate_or_lose (bar),
1324   v : bar (3),
1325   [is (?get ('fpprintprec, '?assign) = false),
1326    v,
1327    [f1 (), f2 (), arr [1]]]);
1328 [false,
1329  [[42, 69, "c"],
1330   [42, 123, "b"]],
1331  [0, 123, "a"]];
1333 (kill (bar), 0);
1336 /* This is testing to make sure there are no bad interactions
1337  * between the usual local cleanup and errcatch cleanup (this
1338  * also mixes the interpreted and translated cases).  This test
1339  * is also ugly.
1341  * The original implementation of local properties (from decades
1342  * ago) not only failed to clean up local properties at all, but
1343  * it wasn't even setting up the internal state to keep up with
1344  * these properties correctly.  An initial attempt at fixing bug
1345  * #2976 made this problem clear because with that it was easy to
1346  * cause an infinite loop during certain things like errcatch
1347  * cleanup.
1348  */
1349 block ([translate : false,
1350         vi, vt],
1351   local (f3),
1352   f3 () := -10,
1353   baz1 () :=
1354     (error ("oops 1"),
1355      local (f4),
1356      f4 () := 0),
1357   baz2 () :=
1358     (local (f5),
1359      f5 () := 1,
1360      error ("oops 2")),
1361   translate_or_lose (baz1, baz2),
1362   baz_test () :=
1363     [block (
1364        local (f3),
1365        f3 () := -1,
1366        errcatch (baz1 ()),
1367        f3 ()),
1368      block (
1369        local (f3),
1370        f3 () := -2,
1371        errcatch (baz2 ()),
1372        f3 ())],
1373   vi : baz_test (),
1374   translate_or_lose (baz_test),
1375   vt : baz_test (),
1376   [vi,
1377    vt,
1378    is (f3 () = -10),
1379    is (f4 () = 0),
1380    is (f5 () = 1)]);
1381 [[-1, -2],
1382  [-1, -2],
1383  true,
1384  false,
1385  false];
1387 /* The internal LOCLIST used by local should be empty right now */
1388 ?null (?loclist);
1389 true;
1391 (kill (baz1, baz2, baz_test), 0);
1394 /***** This ends the bug #2976 tests *****/
1396 /* compile wasn't always compiling the correct function
1398  * This test not only depends on the internal details of how certain
1399  * functions are currently translated, but it also depends on internal
1400  * details about how DEFMFUN defines functions.  This also doesn't
1401  * really test that the correct function gets compiled because the
1402  * lisp implementation could have just compiled it itself anyway.  Ugh.
1403  */
1405 (foo () := 1,
1406  compile_or_lose (foo),
1407  ?compiled\-function\-p (?symbol\-function (?get (foo, ?impl\-name))));
1408 true;
1410 (kill (foo), 0);
1413 /* Some internal function definitions and compiler macros were not
1414  * being cleaned up, and this could cause confusing and bogus results
1415  * when an outdated compiler macro was being used.
1417  * Specifically one problem we had involved translating a function,
1418  * redefining it and then translating the new definition.  The internal
1419  * function and compiler macro from the original function could be used
1420  * when compiling calls to the new function if they were not overwritten.
1422  * This all depended on lisp implementation-dependent behavior because
1423  * implementations are not required to ever use compiler macros.  Ugh.
1425  * This test also depends on internal details of how certain functions
1426  * are currently translated.  Double ugh.
1427  */
1429 (foo () := 0,
1430  translate_or_lose (foo),
1431  kill (foo),
1432  foo ([l]) := l,
1433  translate_or_lose (foo),
1434  test1 () := foo (),
1435  test2 () := foo (1, 2, 3),
1436  compile_or_lose (test1, test2),
1437  /* Previously we observed test1 returning 0 and test2 causing a lisp
1438   * error because the compiler macro and old internal function from
1439   * the first foo were being used.
1440   */
1441  [test1 (), test2 ()]);
1442 [[], [1, 2, 3]];
1444 (kill (foo, test1, test2), 0);
1447 /* https://stackoverflow.com/questions/64631208/compilation-global-variables-with-warning
1449  * First verify that error_syms and niceindicespref assignments work as expected.
1450  */
1452 kill (aa, bb, cc);
1453 done;
1455 errcatch (error_syms: 123);
1458 errcatch (error_syms: [aa, bb, 123]);
1461 error_syms: [aa, bb, cc];
1462 [aa, bb, cc];
1464 errcatch (niceindicespref: 123);
1467 errcatch (niceindicespref: []);
1470 niceindicespref: [aa, bb, cc];
1471 [aa, bb, cc];
1473 (reset (error_syms, niceindicespref), 0);
1476 /* now the example from the Stackoverflow question */
1478 (program_content:
1479 "define_variable(foo, true, boolean)$
1480 foo: true$
1482 exprp(that) := if foo = false and listp(that) and not emptyp(that) and member(that[1], [\"+\", \"*\"]) then(foo: true, true)$
1483 matchdeclare(exprm, exprp)$
1484 defrule(rule_1, exprm, subst(exprm[1], \"[\", exprm[2]))$
1486 calc(list) := block([steps: []],
1487 while foo do(
1488     steps: endcons(list, steps),
1489     foo: false,
1490     list: applyb1(list, rule_1)
1492 steps
1495 calc_result: calc([\"+\", [[\"*\", [1, 2, 3]], [\"+\", [3, 4, 6]]]]);",
1496 program_file_name: sconcat (maxima_tempdir, "/tmp_program.mac"),
1497 with_stdout (program_file_name, print (program_content)),
1501 kill (calc_result);
1502 done;
1504 ([file_name_original, file_name_LISP, file_name_UNLISP, file_name_compiled]: compile_file (program_file_name), 0);
1507 stringp (file_name_compiled);
1508 true;
1510 calc_result;
1511 calc_result;
1513 (load (file_name_compiled),
1514  calc_result);
1515 [["+", [["*", [1, 2, 3]], ["+", [3, 4, 6]]]],
1516  ["+", [6, ["+", [3, 4, 6]]]],
1517  ["+", [6, 13]],
1518  19];
1520 (kill (program_content, program_file_name, file_name_original, file_name_LISP, file_name_UNLISP, file_name_compiled, calc_result), 0);
1524 /* Some additional basic tests for functions with rest args */
1526 block ([translate : false],
1527   foo ([r]) := r,
1528   bar (a, b, [c]) := [a, b, c],
1529   test () :=
1530     [foo (),
1531      foo (1),
1532      foo (1, 2, 3),
1533      errcatch (bar ()),
1534      errcatch (bar (1)),
1535      bar (1, 2),
1536      bar (1, 2, 3),
1537      bar (1, 2, 3, 4, 5)],
1539   /* l1: foo, bar and test are interpreted */
1540   l1 : test (),
1542   /* l2: foo and bar are translated, and test is interpreted */
1543   translate_or_lose (foo, bar),
1544   l2 : test (),
1546   /* l3: foo, bar and test are translated */
1547   translate_or_lose (test),
1548   l3 : test (),
1550   [is (l1 = l2),
1551    is (l2 = l3),
1552    l1]);
1553 [true,
1554  true,
1555  [[],
1556   [1],
1557   [1, 2, 3],
1558   [],
1559   [],
1560   [1, 2, []],
1561   [1, 2, [3]],
1562   [1, 2, [3, 4, 5]]]];
1564 (kill (foo, bar, test, l1, l2, l3), 0);
1567 /* Attempting to translate a macro with a rest arg always caused an
1568  * error during translation because the translator was constructing
1569  * bogus Maclisp-style lexpr lambda expressions.
1570  */
1572 block ([translate : false],
1573   foo ([r]) ::=
1574     buildq ([r], ['r, r]),
1575   bar (a, b, [c]) ::=
1576     buildq ([a, b, c], ['a, a, 'b, b, 'c, c]),
1577   test1 () :=
1578     block ([x : 1, z : 3],
1579       [foo (),
1580        foo (x),
1581        foo (x, y, z),
1582        bar (x, y),
1583        bar (x, y, z),
1584        bar (x, y, z, 4, 5, 6)]),
1585   /* test2 cannot be translated due to the WNA error during macro
1586    * expansion, but we can call and test it in the interpreter
1587    */
1588   test2 () :=
1589     [errcatch (bar ()),
1590      errcatch (bar (1))],
1592   /* l1: foo, bar and test1 are interpreted */
1593   l1 : test1 (),
1595   /* l2: foo and bar are translated, and test1 is interpreted */
1596   translate_or_lose (foo, bar),
1597   l2 : test1 (),
1599   /* l3: foo, bar and test1 are translated */
1600   translate_or_lose (test1),
1601   l3 : test1 (),
1603   [test2 (),
1604    is (l1 = l2),
1605    is (l2 = l3),
1606    l1]);
1607 [[[], []],
1608  true,
1609  true,
1610  [[[], []],
1611   [['x], [1]],
1612   [['x, 'y, 'z], [1, 'y, 3]],
1613   ['x, 1, 'y, 'y, [], []],
1614   ['x, 1, 'y, 'y, ['z], [3]],
1615   ['x, 1, 'y, 'y, ['z, 4, 5, 6], [3, 4, 5, 6]]]];
1617 (kill (foo, bar, test1, test2, l1, l2, l3), 0);
1620 /* Some additional basic tests for conditionals.
1622  * We test both elseif and else-if ("else if").
1623  */
1625 block ([translate : false],
1626   mysignum1 (x) := if x > 0 then 1 elseif  x < 0 then -1 else 0,
1627   mysignum2 (x) := if x > 0 then 1 else if x < 0 then -1 else 0,
1628   foo () :=
1629     [if true then 1,
1630      if false then 1,
1631      if true then 1 else 2,
1632      if false then 1 else 2,
1633      if 1 < 2 then 'y,
1634      if 1 < 2 then 'y else 'n,
1635      if 1 > 2 then 'n,
1636      if 1 > 2 then 'n else 'y,
1637      if 1 > 2 then 'n elseif  1 = 2 then 'n else 'y,
1638      if 1 > 2 then 'n else if 1 = 2 then 'n else 'y,
1639      mysignum1 (-3),
1640      mysignum2 (-3),
1641      mysignum1 (0),
1642      mysignum2 (0),
1643      mysignum1 (2),
1644      mysignum2 (2)],
1645   l1 : foo (),
1646   translate_or_lose (mysignum1, mysignum2, foo),
1647   l2 : foo (),
1648   [is (l1 = l2),
1649    l2]);
1650 [true,
1651  [1, false, 1, 2, 'y, 'y, false, 'y, 'y, 'y, -1, -1, 0, 0, 1, 1]];
1653 (kill (mysignum1, mysignum2, foo, l1, l2), 0);
1656 /* Bogus translations of nested conditionals in elseif clauses
1658  * The translation of a conditional with another conditional nested
1659  * directly under an elseif clause was totally wrong.  Using else-if
1660  * ("else if") instead of elseif would work fine.
1663  * We use the with_both_elseifs macro so we can test both elseif and
1664  * else-if without having to duplicate portions of the tests below.
1665  * Give this macro a conditional expression with elseifs and it will
1666  * expand into a list: the first element is the same expression given
1667  * to it (with elseifs), and the second element is that same expression
1668  * rewritten to use else-ifs instead of elseifs.
1669  */
1671 (to_else_if (expr) :=
1672    if mapatom (expr) then
1673      expr
1674    else
1675      block ([op : op (expr), args : args (expr)],
1676        if op = "if" and length (args) > 4 then
1677          funmake (op, map ('to_else_if, append (firstn (args, 2), [true, funmake (op, rest (args, 2))])))
1678        else
1679          funmake (op, map ('to_else_if, args))),
1680  with_both_elseifs (expr) ::=
1681    buildq ([expr, texpr : to_else_if (expr)],
1682      [expr, texpr]),
1683   0);
1686 block ([translate : false],
1687   foo () :=
1688     with_both_elseifs (
1689       if false then
1690         'lose1
1691       elseif false then
1692         'lose2
1693       elseif false then
1694         if true then
1695           'lose3
1696         else
1697           'lose4
1698       else
1699         'win),
1701   /* l1: foo is interpreted */
1702   l1 : foo (),
1704   translate_or_lose (foo),
1706   /* l2: foo is translated
1707    *
1708    * foo used to give lose3 instead of win in the elseif case.
1709    */
1710   l2 : foo (),
1712   [is (l1 = l2),
1713    l2]);
1714 [true,
1715  ['win, 'win]];
1717 block ([translate : false],
1718   /* There is nothing special about bar here.  This is just some
1719    * function that has several branches with nested conditionals.
1720    */
1721   bar (x) :=
1722     with_both_elseifs (
1723       if x > 5 then
1724         if x > 7 then
1725           'more_than_seven
1726         elseif x > 6 then
1727           'seven
1728         else
1729           'six
1730       elseif x > 2 then
1731         if x > 4 then
1732           'five
1733         elseif x > 3 then
1734           'four
1735         else
1736           'three
1737       elseif x >= 0 then
1738         if x > 1 then
1739           'two
1740         elseif x > 0 then
1741           'one
1742         else
1743           'zero
1744       else
1745         'negative),
1747   /* We test bar with the integers -2 to 9 */
1748   inputs : makelist (k, k, -2, 9),
1750   /* l1: bar is interpreted */
1751   l1 : map (bar, inputs),
1753   translate_or_lose (bar),
1755   /* l2: bar is translated
1756    *
1757    * bar used to give incorrect results in the elseif case for every
1758    * number less than or equal to 2 (which means we got incorrect
1759    * results for the integers -2 to 2 in this test).
1760    */
1761   l2 : map (bar, inputs),
1763   [is (l2 = l1),
1764    l2]);
1765 [true,
1766  [['negative, 'negative],
1767   ['negative, 'negative],
1768   ['zero, 'zero],
1769   ['one, 'one],
1770   ['two, 'two],
1771   ['three, 'three],
1772   ['four, 'four],
1773   ['five, 'five],
1774   ['six, 'six],
1775   ['seven, 'seven],
1776   ['more_than_seven, 'more_than_seven],
1777   ['more_than_seven, 'more_than_seven]]];
1779 (kill (foo, bar, l1, l2, inputs, to_else_if, with_both_elseifs), 0);
1782 /* Bogus translations of conditionals with tests that translated to T
1783  * and consequents that translated to NIL.
1784  */
1786 block ([translate : false],
1787   foo () :=
1788     [if true then false else 1,
1789      if true then false elseif true then 1 else 2,
1790      if false then true elseif true then false else 1],
1792   /* l1: foo is interpreted */
1793   l1 : foo (),
1795   translate_or_lose (foo),
1797   /* l2: foo is translated
1798    *
1799    * foo used to return [1, 1, 1]
1800    */
1801   l2 : foo (),
1803   [is (l2 = l1),
1804    l2]);
1805 [true,
1806  [false, false, false]];
1808 (kill (foo, l1, l2), 0);
1811 /* Bug #3704: Translator gives internal error
1813  * The hyper_to_summand function is from the bug report.
1814  */
1816 (hyper_to_summand(e,k) := subst(hypergeometric = lambda([P,Q,x], 
1817     P : xreduce("*", map(lambda([zz], pochhammer(zz,k)),P)),
1818     Q : xreduce("*", map(lambda([zz], pochhammer(zz,k)),Q)),
1819     P*x^k/(k! * Q)),e),
1820  l1 : hyper_to_summand (hypergeometric ([1/2], [2/5], x), 2),
1821  translate_or_lose (hyper_to_summand),
1822  l2 : hyper_to_summand (hypergeometric ([1/2], [2/5], x), 2),
1823  [is (l1 = l2), l2]);
1824 [true, 75 * x^2 / 112];
1826 (foo () := lambda ([], x!),
1827  translate_or_lose (foo),
1828  block ([x : 5], foo () ()));
1829 120;
1831 (kill (hyper_to_summand, foo, l1, l2), 0);
1834 /* go tags can be integers
1836  * This has been allowed, but it used to give a warning and an extra
1837  * trivial run through the translator to translate the integer go tags.
1838  * Now we allow integers directly without giving a warning.
1840  * We don't actually bother to check for warnings in the test below.
1841  * We're really just verifying that using an integer go tag works.
1842  */
1844 block ([translate : false],
1845   foo () := block ([i : 0], tag, i : i + 1, if i < 5 then go (tag), i),
1846   bar () := block ([i : 0], 123, i : i + 1, if i < 5 then go (123), i),
1847   l1 : [foo (), bar ()],
1848   translate_or_lose (foo, bar),
1849   l2 : [foo (), bar ()],
1850   [is (l1 = l2), l2]);
1851 [true, [5, 5]];
1853 (kill (foo, bar, l1, l2), 0);
1856 /* A bug in MARRAYREF caused things like translated array references
1857  * to yield MQAPPLY expressions with an incorrect header.
1858  */
1860 block ([translate : false],
1861   foo () := 'baz () [1],
1862   bar () := 'baz () [1, 2, 3],
1863   l1 : [foo (), bar ()],
1864   translate_or_lose (foo, bar),
1865   l2 : [foo (), bar ()],
1866   [is (l1 = l2), l2]);
1867 [true, ['baz () [1], 'baz () [1, 2, 3]]];
1869 (kill (foo, bar, l1, l2), 0);
1872 /* A bug in MARRAYREF caused bogus indexing into hash tables and fast
1873  * arrays.  This affected things like translated array references.
1874  */
1876 block ([translate : false,
1877         use_fast_arrays : true],
1879   foo () := block ([a],
1880               a[false] : 'wtf,
1881               a[1] : 2,
1882               a[1]),
1884   /* This would correctly yield 2 */
1885   l1 : foo (),
1887   translate_or_lose (foo),
1889   /* This used to incorrectly yield wtf */
1890   l2 : foo (),
1892   [is (l1 = l2), l2]);
1893 [true, 2];
1895 (kill (foo, l1, l2), 0);
1898 /* A bug in MARRAYREF caused things like translated array references
1899  * to yield expressions with an incorrect header.
1900  */
1902 block ([translate : false],
1903   foo () := block ([a],
1904               local (a),
1905               array (a, complete, 5),
1906               a[3]),
1908   /* This would correctly yield a[3] */
1909   l1 : foo(),
1911   translate_or_lose (foo),
1913   /* This would incorrectly yield a(3) */
1914   l2 : foo(),
1916   [is (l1 = l2), l2]);
1917 [true, 'a[3]];
1919 (kill (foo, l1, l2), 0);
1922 /* When translate_fast_arrays:true, a lisp error would occur at runtime
1923  * during an attempted MQAPPLY array assignment
1924  */
1926 block ([translate : false],
1927   foo () := block ([a],
1928               local (a, b),
1929               a : make_array ('fixnum, 5),
1930               b () := a,
1931               b () [3] : 17,
1932               b () [3]),
1934   /* This would correctly yield 17 */
1935   l1 : foo(),
1937   block ([translate_fast_arrays : false],
1938     translate_or_lose (foo)),
1940   /* This would correctly yield 17 */
1941   l2 : foo(),
1943   block ([translate_fast_arrays : true],
1944     translate_or_lose (foo)),
1946   /* This would cause a lisp error */
1947   l3 : foo(),
1949   [is (l1 = l2), is (l2 = l3), l3]);
1950 [true, true, 17];
1952 (kill (foo, l1, l2, l3), 0);
1955 /* The string "**" no longer translates to the string "^".
1956  * This test compares the interpreted and translated results.
1957  */
1959 block ([translate : false],
1960   foo () := ["^", "^" (2, 3), apply ("^", [2, 3]),
1961              "**", "**" (2, 3), apply ("**", [2, 3])],
1962   l1 : foo (),
1963   translate_or_lose (foo),
1964   l2 : foo (),
1965   [l2, is (l1 = l2)]);
1966 [["^", 8, 8, "**", 8, 8], true];
1968 (kill (foo, l1, l2), 0);
1971 /* Attempting to translate some atoms like lisp arrays would
1972  * cause lisp errors during translation.
1973  */
1975 (a : make_array (fixnum, 1),
1976  a[0] : 13,
1977  define (foo (), a),
1978  translate_or_lose (foo),
1979  listarray (foo ()));
1980 [13];
1982 (kill (foo, a), 0);
1985 /* Simple tests for catch and throw */
1987 block ([translate : false, l1, l2],
1988   local (foo, bar, baz),
1990   foo (p) := if p then throw (13) else 2,
1991   bar () := catch (1, foo (false), 3),
1992   baz () := catch (1, foo (true), 3),
1994   l1 : [bar (), baz ()],
1996   translate_or_lose (foo, bar, baz),
1998   l2 : [bar (), baz ()],
2000   [l2, is (l1 = l2)]);
2001 [[3, 13], true];
2003 block ([translate : false, l1, l2],
2004   local (foo, bar),
2006   foo (p) := throw (if p then 1/2 else 'other),
2007   bar (p) := 1 + catch (foo (p), 2),
2009   l1 : [bar (true), bar (false)],
2011   translate_or_lose (foo, bar),
2013   l2 : [bar (true), bar (false)],
2015   [l2, is (l1 = l2)]);
2016 [[3/2, 1 + 'other], true];
2018 (kill (foo, bar), 0);
2021 /* Translating a define_variable form with translate (but not
2022  * translate_file or compfile) used to invoke undefined behavior.
2023  * This would cause a lisp error during translation under some
2024  * (but not all) lisp implementations.
2025  */
2027 block ([translate : false],
2028   local (foo),
2029   foo () := (define_variable (x, 1, fixnum), x),
2030   translate_or_lose (foo),
2031   foo ());
2034 (kill (foo, x), 0);
2037 /* If local was used on a matchdeclared pattern variable, and this
2038  * was all translated with something besides translate_file (e.g.,
2039  * translate, compfile, etc.), then the MATCHDECLARE property would
2040  * not be on the pattern variable.
2041  */
2043 block ([translate : false, l1, l2],
2044   local (foo),
2046   foo () := (local (x), matchdeclare (x, true), let (a * x, x), letsimp (a * q)),
2048   /* This would yield q */
2049   l1 : foo (),
2051   translate_or_lose (foo),
2053   /* This used to yield a*q */
2054   l2 : foo (),
2056   [l2, is (l1 = l2)]);
2057 [q, true];
2059 (kill (foo), 0);
2062 /* Rest args are now allowed in lambda expressions in MQAPPLY
2063  * lambda forms
2064  */
2066 block ([translate : false, l1, l2],
2067   local (foo, bar, baz),
2069   /* foo used to fail to translate due to the rest arg */
2070   foo () :=
2071     block ([x : 1, z : 3],
2072       lambda ([[x]], x) (x, x + 1, z)),
2073   bar () :=
2074     block ([x : 2, z : 4],
2075       apply (lambda ([[x]], x), [x, x + 1, z])),
2076   baz () :=
2077     block ([x : 3, z : 5],
2078       block ([f : lambda ([[x]], x)],
2079         f (x, x + 1, z))),
2081   l1 : [foo (), bar (), baz ()],
2083   translate_or_lose (foo, bar, baz),
2085   l2 : [foo (), bar (), baz ()],
2087   [l1, is (l1 = l2)]);
2088 [[[1, 2, 3],[2, 3, 4],[3, 4, 5]], true];
2090 /* Validation has been improved for lambda expressions in MQAPPLY
2091  * lambda forms
2092  */
2094 block ([translate : false],
2095   local (foo, bar),
2097   /* These should both fail to translate */
2098   foo () := lambda ([]) (),
2099   bar () := lambda ([x, x], x) (1, 2),
2101   translate (foo, bar));
2104 /* The translation of array functions was broken for decades */
2106 block ([translate : false, l1, l2],
2107   local (foo, bar),
2109   foo[x] := x,
2110   bar[n] := if n = 1 then 1 else n * bar[n - 1],
2112   l1 : [foo[0], foo[5], bar[5], bar[10]],
2114   translate_or_lose (foo, bar),
2116   l2 : [foo[0], foo[5], bar[5], bar[10]],
2118   [l1, is (l1 = l2)]);
2119 [[0, 5, 120, 3628800], true];
2121 (kill (foo, bar), 0);
2124 /* The translation of upward funargs (including those created by
2125  * subscripted functions) easily lead to lisp errors.
2126  */
2128 /* Tests involving returned lambdas without free vars that were
2129  * bound during definition
2130  */
2131 block ([l1, l2,
2132         translate : false,
2133         listarith : true],
2134   local (foo, bar, test),
2136   foo () := lambda ([x], 2 * x + q),
2137   bar () := lambda ([x, [y]], x * y + q),
2139   test () :=
2140     block ([f : foo (),
2141             b : bar ()],
2142       [f (3), f (5), b (2, 3, 4), b (5, 6, 7)]),
2144   l1 : test (),
2146   translate_or_lose (foo, bar),
2148   l2 : test (),
2150   [l2, is (l1 = l2)]);
2151 [['q + 6, 'q + 10, ['q + 6, 'q + 8], ['q + 30, 'q + 35]],
2152  true];
2154 (kill (foo, bar), 0);
2157 /* Tests involving returned lambdas with free vars that were
2158  * bound during definition.  These do not cause the capture of
2159  * values.
2160  */
2161 block ([l1, l2,
2162         x : 'ux,
2163         translate : false,
2164         listarith : true],
2165   local (foo, bar, baz, test),
2167   foo (x) := lambda ([y], x + y + q),
2168   bar (x) := lambda ([y, [z]], q + x + y * z),
2169   baz (v) := lambda ([], v),
2171   test () :=
2172     block ([f : foo (3),
2173             b : bar (4),
2174             c : baz (5)],
2175       [f (5), b (2, 3, 4), c ()]),
2177   l1 : test (),
2179   translate_or_lose (foo, bar, baz),
2181   l2 : test (),
2183   [l2, is (l1 = l2)]);
2184 [['q + 'ux + 5,
2185   ['q + 'ux + 6, 'q + 'ux + 8],
2186   'v],
2187  true];
2189 (kill (foo, bar, baz), 0);
2192 /* Tests involving subscripted functions.  These do cause the capture
2193  * of values.
2194  */
2195 block ([l1, l2,
2196         x : 'ux, y : 'uy,
2197         translate : false],
2198   local (foo, bar, baz, def, test),
2200   def () := (
2201     foo[x, y](a, b) := [x, y, a, b, q],
2202     bar[x, y](a, [b]) := [x, y, a, b, q],
2203     baz[v]() := v),
2205   test () :=
2206     block ([f : foo[1, 2],
2207             b : bar[3, 4],
2208             c : baz[5]],
2209       [f (6, 7), b (8, 9, 10), c ()]),
2211   def (),
2213   l1 : test (),
2215   /* just kill and redefine */
2217   kill (foo, bar, baz),
2219   def (),
2221   translate_or_lose (foo, bar, baz),
2223   l2 : test (),
2225   [l2, is (l1 = l2)]);
2226 [[[1, 2, 6, 7, 'q],
2227   [3, 4, 8, [9, 10], 'q],
2228   5],
2229  true];
2231 (kill (foo, bar, baz), 0);
2234 /* More tests involving multiple nested lambdas */
2235 block ([l1, l2,
2236         x : 'ux, y : 'uy, z : 'uz,
2237         translate : false],
2238   local (foo, bar, baz, quux, def, test),
2240   def () := (
2241     /* nothing should be captured */
2242     foo (x) := lambda ([y], lambda ([z], [x, y, z])),
2243     /* x should be captured and used */
2244     bar[x](y) := lambda ([z], [x, y, z]),
2245     /* x should be captured and used */
2246     baz[x](y) := lambda ([z], lambda ([], [x, y, z])),
2247     /* nothing should be captured since x is bound by the inner lambda */
2248     quux[x](y) := lambda ([x], [x, y])),
2250   test () :=
2251     block ([a : foo (1),
2252             b : bar[2],
2253             c : baz[3],
2254             d : quux[4]],
2255       [a (10) (11), b (12) (13), c (14) (15) (), d (16) (17)]),
2257   def (),
2259   l1 : test (),
2261   /* just kill and redefine */
2263   kill (foo, bar, baz, quux),
2265   def (),
2267   translate_or_lose (foo, bar, baz, quux),
2269   l2 : test (),
2271   [l2, is (l1 = l2)]);
2272 [[['ux, 'uy, 11],
2273   [2, 'uy, 13],
2274   [3, 'uy, 'uz],
2275   [17, 'uy]],
2276  true];
2278 (kill (foo, bar, baz, quux), 0);
2281 /* The translator was not correctly determining the mode of expressions
2282  * when a boolean mode was involved.
2284  * It was easy to get lisp errors.
2285  */
2286 block ([translate : false, l1, l2],
2287   local (test),
2289   foo () :=
2290     [  1 + if true then 0,
2291        1 + if true then 0.0,
2292      1.0 + if true then 0,
2293      1.0 + if true then 0.0,
2295        1 + if false then 0,
2296        1 + if false then 0.0,
2297      1.0 + if false then 0,
2298      1.0 + if false then 0.0],
2300   bar (x) :=
2301     [  1 + if x then 0,
2302        1 + if x then 0.0,
2303      1.0 + if x then 0,
2304      1.0 + if x then 0.0],
2306   test () :=
2307     block ([res : []],
2308       for prederror in [true, false] do
2309         push (foo (), res),
2310         for x in [true, false] do
2311           push (bar (x), res),
2312       res),
2314   l1 : test (),
2316   translate_or_lose (foo, bar),
2318   l2 : test (),
2320   is (l1 = l2));
2321 true;
2323 (kill (foo, bar), 0);
2327  * Bug #4008: translator and prederror
2328  */
2330 (kill (pred, foo, bar, x, r), 0);
2333 block ([translate : false, l1, l2],
2334   local (test),
2336   foo (n, q, x) :=
2337     [if true then q + r,
2338      if false then q + r,
2340      if x then q,
2341      if not x then q,
2342      if not not x then q,
2343      if not not not x then q,
2345      n + if x then q + r,
2346      n + if not x then q + r,
2347      n + if not not x then q + r,
2348      n + if not not not x then q + r],
2350   test () :=
2351     block ([res : []],
2352       for prederror in [true, false] do
2353         for n in [1, 1.0, %i, 1.0 * %i] do
2354           for q in [1, 1.0, %i, 1.0 * %i, 'z] do
2355             for x in [true, false] do
2356               push (foo (n, q, x), res),
2357       res),
2359   l1 : test (),
2361   translate_or_lose (foo),
2363   l2 : test (),
2365   is (l1 = l2));
2366 true;
2368 (kill (foo), 0);
2371 block ([translate : false, l1, l2],
2372   local (test),
2374   foo (x, y) :=
2375     block ([q : 'z],
2376       [if "and" () then q else r,
2377        if "and" (x) then q else r,
2378        if "and" (y) then q else r,
2379        if x and y then q else r,
2380        if not x and y then q else r,
2381        if x and not y then q else r,
2382        if not x and not y then q else r,
2383        if not (x and y) then q else r,
2384        if not (not x and y) then q else r,
2385        if not (x and not y) then q else r,
2386        if not (not x and not y) then q else r,
2388        if "or" () then q else r,
2389        if "or" (x) then q else r,
2390        if "or" (y) then q else r,
2391        if x or y then q else r,
2392        if not x or y then q else r,
2393        if x or not y then q else r,
2394        if not x or not y then q else r,
2395        if not (x or y) then q else r,
2396        if not (not x or y) then q else r,
2397        if not (x or not y) then q else r,
2398        if not (not x or not y) then q else r]),
2400   test () :=
2401     block ([res : []],
2402       for prederror in [true, false] do
2403         for x in [true, false] do
2404           for y in [true, false] do
2405             push (foo (x, y), res),
2406       res),
2408   l1 : test (),
2410   translate_or_lose (foo),
2412   l2 : test (),
2414   is (l1 = l2));
2415 true;
2417 (kill (foo), 0);
2420 block ([translate : false, l1, l2],
2421   local (test, make_fun),
2423   make_fun (name, pr) ::=
2424     buildq ([name, pr],
2425       name (x, y) :=
2426         block ([q : 'z],
2427           [pr ("and" ()),
2428            pr ("and" (x)),
2429            pr ("and" (y)),
2430            pr (x and y),
2431            pr (not x and y),
2432            pr (x and not y),
2433            pr (not x and not y),
2434            pr (not (x and y)),
2435            pr (not (not x and y)),
2436            pr (not (x and not y)),
2437            pr (not (not x and not y)),
2439            pr ("or" ()),
2440            pr ("or" (x)),
2441            pr ("or" (y)),
2442            pr (x or y),
2443            pr (not x or y),
2444            pr (x or not y),
2445            pr (not x or not y),
2446            pr (not (x or y)),
2447            pr (not (not x or y)),
2448            pr (not (x or not y)),
2449            pr (not (not x or not y))])),
2451   make_fun (foo, is),
2452   make_fun (bar, maybe),
2454   test () :=
2455     block ([res : []],
2456       for prederror in [true, false] do
2457         for x in [true, false] do
2458           for y in [true, false] do (
2459             push (foo (x, y), res),
2460             push (bar (x, y), res)),
2461       res),
2463   l1 : test (),
2465   translate_or_lose (foo, bar),
2467   l2 : test (),
2469   is (l1 = l2));
2470 true;
2472 (kill (foo, bar), 0);
2475 block ([translate : false, l1, l2],
2476   local (test),
2478   pred (a, b) := equal (a, b),
2480   foo (x, y) :=
2481     block ([q : 'z],
2482       [if x < y then q else r,
2483        if not (x < y) then q else r,
2484        if x <= y then q else r,
2485        if not (x <= y) then q else r,
2486        if x > y then q else r,
2487        if not (x > y) then q else r,
2488        if x >= y then q else r,
2489        if not (x >= y) then q else r,
2491        if x = y then q else r,
2492        if x # y then q else r,
2493        if not (x = y) then q else r,
2494        if not (x # y) then q else r,
2495        if not not (x = y) then q else r,
2496        if not not (x # y) then q else r,
2497        if not not not (x = y) then q else r,
2498        if not not not (x # y) then q else r,
2500        if equal (x, y) then q else r,
2501        if notequal (x, y) then q else r,
2502        if not equal (x, y) then q else r,
2503        if not not equal (x, y) then q else r,
2504        if not notequal (x, y) then q else r,
2505        if not not not equal (x, y) then q else r,
2506        if not not notequal (x, y) then q else r,
2508        if pred (x, y) then q else r,
2509        if not pred (x, y) then q else r,
2510        if not not pred (x, y) then q else r,
2511        if not not not pred (x, y) then q else r]),
2513   test () :=
2514     block ([res : []],
2515       for prederror in [true, false] do
2516         for x in [1, 2] do
2517           for y in [1, 2] do
2518             push (foo (x, y), res),
2519       res),
2521   l1 : test (),
2523   translate_or_lose (pred, foo),
2525   l2 : test (),
2527   is (l1 = l2));
2528 true;
2530 (kill (pred, foo), 0);
2533 block ([translate : false, l1, l2],
2534   local (test, make_fun),
2536   pred (a, b) := equal (a, b),
2538   make_fun (name, pr) ::=
2539     buildq ([name, pr],
2540       name (x, y) :=
2541         block ([q : 'z],
2542           [pr (x = y),
2543            pr (x # y),
2544            pr (not (x = y)),
2545            pr (not (x # y)),
2546            pr (not not (x = y)),
2547            pr (not not (x # y)),
2548            pr (not not not (x = y)),
2549            pr (not not not (x # y)),
2551            pr (equal (x, y)),
2552            pr (not equal (x, y)),
2553            pr (notequal (x, y)),
2554            pr (not not equal (x, y)),
2555            pr (not notequal (x, y)),
2556            pr (not not not equal (x, y)),
2557            pr (not not notequal (x, y)),
2559            pr (pred (x, y)),
2560            pr (not pred (x, y)),
2561            pr (not not pred (x, y)),
2562            pr (not not not pred (x, y))])),
2564   make_fun (foo, is),
2565   make_fun (bar, maybe),
2567   test () :=
2568     block ([res : []],
2569       for prederror in [true, false] do
2570         for x in [1, 2] do
2571           for y in [1, 2] do (
2572             push (foo (x, y), res),
2573             push (bar (x, y), res)),
2574       res),
2576   l1 : test (),
2578   translate_or_lose (pred, foo, bar),
2580   l2 : test (),
2582   is (l1 = l2));
2583 true;
2585 (kill (pred, foo, bar), 0);
2588 block ([translate : false, l1, l2],
2589   local (test),
2591   foo (x, q) :=
2592     [if (1, 2, q, x) then q else r,
2593      if not (1, 2, q, x) then q else r,
2594      if (1, 2, q, not x) then q else r],
2596   test () :=
2597     block ([res : []],
2598       for prederror in [true, false] do
2599         for x in [true, false] do
2600           push (foo (x, 17), res),
2601       res),
2603   l1 : test (),
2605   translate_or_lose (foo),
2607   l2 : test (),
2609   is (l1 = l2));
2610 true;
2612 (kill (foo), 0);
2615 block ([translate : false, l1, l2],
2616   local (test, make_fun),
2618   make_fun (name, pr) ::=
2619     buildq ([name, pr],
2620       name (x, y) :=
2621         [pr (x),
2622          pr (not x),
2623          pr (not not x),
2624          pr (not not not x),
2626          pr (y),
2627          pr (not y),
2628          pr (not not y),
2629          pr (not not not y),
2631          pr (x and y),
2632          pr (x or y),
2633          pr (not (x and y)),
2634          pr (not (x or y)),
2635          pr (not not (x and y)),
2636          pr (not not (x or y)),
2637          pr (not not not (x and y)),
2638          pr (not not not (x or y)),
2640          pr (x and not y),
2641          pr (x or not y),
2642          pr (x and not not y),
2643          pr (x or not not y),
2644          pr (not (x and not y)),
2645          pr (not (x or not y)),
2646          pr (not (x and not not y)),
2647          pr (not (x or not not y)),
2649          pr (not x and y),
2650          pr (not x or y),
2651          pr (not not x and y),
2652          pr (not not x or y),
2653          pr (not (not x and y)),
2654          pr (not (not x or y)),
2655          pr (not (not not x and y)),
2656          pr (not (not not x or y)),
2658          pr (not x and not y),
2659          pr (not x or not y),
2660          pr (not (not x and not y)),
2661          pr (not (not x or not y)),
2663          pr (x > 1),
2664          pr (not x > 1),
2665          pr (x > 1 and y),
2666          pr (x > 1 or y),
2667          pr (x > 1 and not y),
2668          pr (x > 1 or not y),
2669          pr (not x > 1 and y),
2670          pr (not x > 1 or y),
2671          pr (not x > 1 and not y),
2672          pr (not x > 1 or not y),
2674          pr (y <= 1),
2675          pr (not y <= 1),
2676          pr (x and y <= 1),
2677          pr (x or y <= 1),
2678          pr (x and not y <= 1),
2679          pr (x or not y <= 1),
2680          pr (not x and y <= 1),
2681          pr (not x or y <= 1),
2682          pr (not x and not y <= 1),
2683          pr (not x or not y <= 1)]),
2685   make_fun (foo, is),
2686   make_fun (bar, maybe),
2688   test () :=
2689     block ([prederror : false,
2690             l : [true, false, 1, 2.0, 'q, 'q ()],
2691             res : []],
2692       for x in l do
2693         for y in l do (
2694           push (foo (x, y), res),
2695           push (bar (x, y), res)),
2696       res),
2698   l1 : test (),
2700   translate_or_lose (foo, bar),
2702   l2 : test (),
2704   is (l1 = l2));
2705 true;
2707 (kill (foo, bar), 0);
2710 block ([translate : false, l1, l2],
2711   local (test, make_fun),
2713   make_fun (name, pr) ::=
2714     buildq ([name, pr],
2715       name (x) :=
2716         [pr (x <  1),
2717          pr (x <= 1),
2718          pr (x >  1),
2719          pr (x >= 1),
2721          pr (not (x <  1)),
2722          pr (not (x <= 1)),
2723          pr (not (x >  1)),
2724          pr (not (x >= 1)),
2726          pr (not not (x <  1)),
2727          pr (not not (x <= 1)),
2728          pr (not not (x >  1)),
2729          pr (not not (x >= 1)),
2731          pr (x = 1),
2732          pr (x # 1),
2733          pr (not (x = 1)),
2734          pr (not (x # 1)),
2735          pr (not not (x = 1)),
2736          pr (not not (x # 1)),
2738          pr (equal (x, 1)),
2739          pr (notequal (x, 1)),
2740          pr (not equal (x, 1)),
2741          pr (not notequal (x, 1)),
2742          pr (not not equal (x, 1)),
2743          pr (not not notequal (x, 1))]),
2745   make_fun (foo, is),
2746   make_fun (bar, maybe),
2748   test () :=
2749     block ([res : []],
2750       block ([prederror : true],
2751         push (errcatch (foo ('z)), res)),
2752       block ([prederror : false,
2753               l : [0, 0.0, 0.0b0,
2754                    1, 1.0, 1.0b0,
2755                    2, 2.0, 2.0b0,
2756                    %i, 1.0 * %i, 1.0b0 * %i,
2757                    2 * %i, 2.0 * %i, 2.0b0 * %i,
2758                    true, false,
2759                    'z, 'z ()]],
2760         for x in l do (
2761           push (foo (x), res),
2762           push (bar (x), res))),
2763       res),
2765   l1 : test (),
2767   translate_or_lose (foo, bar),
2769   l2 : test (),
2771   is (l1 = l2));
2772 true;
2774 (kill (foo, bar), 0);
2777 block ([translate : false, l1, l2],
2778   local (test),
2780   foo (x, q, prederror) :=
2781     block ([r],
2782       [if x then 0,
2783        if not x then 0,
2784        if not not x then 0,
2785        if not not not x then 0,
2786        if x then q + r,
2787        if not x then q + r,
2788        if not not x then q + r,
2789        if not not not x then q + r,
2790        if x then 1 else 2,
2791        if not x then 1 else 2,
2792        if not not x then 1 else 2,
2793        if not not not x then 1 else 2,
2794        if x then x else q + r,
2795        if not x then x else q + r,
2796        if not not x then x else q + r,
2797        if not not not x then x else q + r,
2798        if x = 1 then x else q + r,
2799        if x # 1 then x else q + r,
2800        if not x = 1 then x else q + r,
2801        if not x # 1 then x else q + r,
2802        if not not x = 1 then x else q + r,
2803        if not not x # 1 then x else q + r,
2804        if not not not x = 1 then x else q + r,
2805        if not not not x # 1 then x else q + r]),
2807   test () :=
2808     block ([l : [true, false, 1, 2.0, 3.0b0, 'z, 'z ()],
2809             res : []],
2810       push (errcatch (foo (1, 2, true)), res),
2811       for x in l do
2812         for q in l do
2813           push (foo (x, q, false), res),
2814       res),
2816   l1 : test (),
2818   translate_or_lose (foo),
2820   l2 : test (),
2822   is (l1 = l2));
2823 true;
2825 (kill (foo), 0);
2828 block ([translate : false, l1, l2],
2829   local (rewritehack, eqhack, test),
2831   /* Take a relational expr and potentially rewrite it in some
2832    * equivalent way, e.g.  x<1  =>  1-x>0
2833    */
2834   rewritehack (r) :=
2835     eval_string_lisp ("(apply #'mevalp2 $r (mop $r) (margs $r))")[1],
2837   /* Translated code can produce relational exprs that are in a
2838    * different, but equivalent, form compared to the exprs produce
2839    * by interpreted code.
2840    *
2841    * Compare two conditionals by requiring that everything matches
2842    * exactly, except possibly the first (only) test.  The tests
2843    * should match exactly after applying rewritehack to them.
2844    */
2845   eqhack (interp, transl) :=
2846     if atom (interp) or atom (transl) or op (interp) # "if" or op (transl) # "if" then
2847       is (interp = transl)
2848     else
2849       is (rest (interp) = rest (transl)
2850           and
2851           rewritehack (first (interp)) = rewritehack (first (transl))),
2853   foo (x) :=
2854     block ([r],
2855       [if x <  1 then x else r,
2856        if x <= 1 then x else r,
2857        if x >  1 then x else r,
2858        if x >= 1 then x else r,
2860        if not (x <  1) then x else r,
2861        if not (x <= 1) then x else r,
2862        if not (x >  1) then x else r,
2863        if not (x >= 1) then x else r,
2865        if not not (x <  1) then x else r,
2866        if not not (x <= 1) then x else r,
2867        if not not (x >  1) then x else r,
2868        if not not (x >= 1) then x else r,
2870        if x = 1 then x else r,
2871        if x # 1 then x else r,
2872        if not (x = 1) then x else r,
2873        if not (x # 1) then x else r,
2874        if not not (x = 1) then x else r,
2875        if not not (x # 1) then x else r,
2877        if equal (x, 1) then x else r,
2878        if notequal (x, 1) then x else r,
2879        if not equal (x, 1) then x else r,
2880        if not notequal (x, 1) then x else r,
2881        if not not equal (x, 1) then x else r,
2882        if not not notequal (x, 1) then x else r]),
2884   test () :=
2885     block ([res : []],
2886       block ([prederror : true],
2887         push (errcatch (foo ('z)), res)),
2888       block ([prederror : false,
2889               l : [0, 0.0, 0.0b0,
2890                    1, 1.0, 1.0b0,
2891                    2, 2.0, 2.0b0,
2892                        %i, 1.0 * %i, 1.0b0 * %i,
2893                    2 * %i, 2.0 * %i, 2.0b0 * %i,
2894                    true, false,
2895                    'z, 'z ()]],
2896         for x in l do
2897           res : append (foo (x), res)),
2898       res),
2900   l1 : test (),
2902   translate_or_lose (foo),
2904   l2 : test (),
2906   every (eqhack, l1, l2));
2907 true;
2909 (kill (foo), 0);
2912 block ([translate : false, l1, l2],
2913   local (test),
2915   foo (x, y, z) :=
2916     block ([r],
2917       [if x >  0 and y >  0 and z >  0 then x + y = z else r,
2918        if x >  0 or  y >  0 or  z >  0 then x + y = z else r,
2919        if x >= 1 and y >= 1 and z >= 1 then x + y = z else r,
2920        if x >= 1 or  y >= 1 or  z >= 1 then x + y = z else r,
2921        if x <= 2 and y <= 2 and z <= 2 then x + y = z else r,
2922        if x <= 2 or  y <= 2 or  z <= 2 then x + y = z else r,
2923        if x <  3 and y <  3 and z <  3 then x + y = z else r,
2924        if x <  3 or  y <  3 or  z <  3 then x + y = z else r]),
2926   test () :=
2927     block ([l : [1, 2.0, 3.0b0, %i],
2928             res : []],
2929       for x in l do
2930         for y in l do
2931           for z in l do
2932             push (foo (x, y, z), res),
2933       res),
2935   l1 : test (),
2937   translate_or_lose (foo),
2939   l2 : test (),
2941   is (l1 = l2));
2942 true;
2944 (kill (foo), 0);
2947 block ([translate : false, l1, l2],
2948   local (test),
2950   foo (p, x, y, z) :=
2951     (modedeclare (p, boolean, x, fixnum, y, flonum, z, number),
2952       block ([r],
2953         [if p and x >  0 and y >  0 and z >  0 then x + y - z else r,
2954          if p or  x >  0 or  y >  0 or  z >  0 then x + y - z else r,
2955          if p and x >= 1 and y >= 1 and z >= 1 then x + y - z else r,
2956          if p or  x >= 1 or  y >= 1 or  z >= 1 then x + y - z else r,
2957          if p and x <= 2 and y <= 2 and z <= 2 then x + y - z else r,
2958          if p or  x <= 2 or  y <= 2 or  z <= 2 then x + y - z else r,
2959          if p and x <  3 and y <  3 and z <  3 then x + y - z else r,
2960          if p or  x <  3 or  y <  3 or  z <  3 then x + y - z else r,
2962          if p and x >  y and y >  z and z >  3 then x + y + z else r,
2963          if p or  x >  y or  y >  z or  z >  3 then x + y + z else r,
2964          if p and x >= y and y >= z and z >= 2 then x + y + z else r,
2965          if p or  x >= y or  y >= z or  z >= 2 then x + y + z else r,
2966          if p and x <= y and y <= z and z <= 1 then x + y + z else r,
2967          if p or  x <= y or  y <= z or  z <= 1 then x + y + z else r,
2968          if p and x <  y and y <  z and z <  0 then x + y + z else r,
2969          if p or  x <  y or  y <  z or  z <  0 then x + y + z else r])),
2971   test () :=
2972     block ([bool : [true, false],
2973             fixl : [0, 1, 2, 3, 4],
2974             flol : [0.0, 1.0, 2.0, 3.0, 4.0],
2975             numl : [0, 1.0, 2, 3.0, 4],
2976             res : []],
2977       for p in bool do
2978         for x in fixl do
2979           for y in flol do
2980             for z in numl do
2981               push (foo (p, x, y, z), res),
2982       res),
2984   l1 : test (),
2986   translate_or_lose (foo),
2988   l2 : test (),
2990   is (l1 = l2));
2991 true;
2993 (kill (foo, p, x, y, z), 0);
2996 block ([translate : false, l1, l2],
2997   local (test),
2999   foo (p, x, y, z) :=
3000     block ([r],
3001       [if p and x and y and z then x + y = z else r,
3002        if p or  x or  y or  z then x + y = z else r,
3004        if p and equal (x, 1) and equal (y, 1) and equal (z, 1) then x + y = z else r,
3005        if p or  equal (x, 1) or  equal (y, 1) or  equal (z, 1) then x + y = z else r,
3007        if not p and not equal (x, 1) and not equal (y, 1) and not equal (z, 1) then x + y = z else r,
3008        if not p or  not equal (x, 1) or  not equal (y, 1) or  not equal (z, 1) then x + y = z else r,
3010        if p and notequal (x, 1) and notequal (y, 1) and notequal (z, 1) then x + y = z else r,
3011        if p or  notequal (x, 1) or  notequal (y, 1) or  notequal (z, 1) then x + y = z else r,
3013        if not p and not notequal (x, 1) and not notequal (y, 1) and not notequal (z, 1) then x + y = z else r,
3014        if not p or  not notequal (x, 1) or  not notequal (y, 1) or  not notequal (z, 1) then x + y = z else r]),
3016   test () :=
3017     block ([prederror : false,
3018             l : [true, false, 1, 2.0, 3.0b0, %i, 'z, 'z ()],
3019             res : []],
3020       for p in [true, false] do
3021         for x in l do
3022           for y in l do
3023             for z in l do
3024               push (foo (p, x, y, z), res),
3025       res),
3027   l1 : test (),
3029   translate_or_lose (foo),
3031   l2 : test (),
3033   is (l1 = l2));
3034 true;
3036 (kill (foo), 0);
3039 block ([translate : false, l1, l2],
3040   local (test),
3042   pred (a, b) := equal (a, b),
3044   foo (x, q) :=
3045     block ([r, var1, var2, v1 : 'var1, v2 : 'var2],
3046       [if pred (x, 1) then x,
3047        if not pred (x, 1) then x,
3048        if pred (x, 1) or pred (x, 2) then x,
3049        if pred (x, 1) then x else q + r,
3050        if not pred (x, 1) then x else q + r,
3051        if pred (x, 1) or pred (x, 2) then x else q + r,
3052        if pred (x, 1) then f (x + q) elseif pred (x, 2) then g (x + q) elseif pred (x, q) then v1 :: r * x else var1 : q * r,
3053        if pred (x, 1) then f (x + q) else if pred (x, 2) then g (x + q) else if pred (x, q) then v2 :: r * x else var2 : q * r,
3054        if pred (x, 1) and q then f (x + q) elseif pred (x, 2) or q then g (x + q) elseif not pred (x, q) then v1 :: r * x else var1 : q * r,
3055        if pred (x, 1) and q then f (x + q) else if pred (x, 2) or q then g (x + q) else if not pred (x, q) then v2 :: r * x else var2 : q * r,
3056        if pred (x, 1) and not q then f (x + q) elseif pred (x, 2) or not q then g (x + q) elseif not pred (x, q) then v1 :: r * x else var1 : q * r,
3057        if pred (x, 1) and not q then f (x + q) else if pred (x, 2) or not q then g (x + q) else if not pred (x, q) then v2 :: r * x else var2 : q * r]),
3059   test () :=
3060     block ([res : []],
3061       block ([prederror : false],
3062         push (errcatch (foo (true, false)), res)),
3063       block ([prederror : false,
3064               l : [true, false, 1, 2.0, 3.0b0, %i, 'z, 'z ()]],
3065         for x in l do
3066           for q in l do
3067             push (foo (x, q), res)),
3068       res),
3070   l1 : test (),
3072   translate_or_lose (pred, foo),
3074   l2 : test (),
3076   is (l1 = l2));
3077 true;
3079 (kill (pred, foo), 0);
3082 block ([translate : false, l1, l2],
3083   local (test),
3085   /* I really want push(x,a) below in foo, bar and baz,
3086    * but the translation of the push special form just
3087    * punts to MEVAL.  I want the loop bodies translated
3088    * better than that, especially in baz, so just do
3089    * a:cons(x,a) everywhere here.
3090    */
3092   foo () :=
3093     [block ([a : []],
3094        for x : 1 thru 5 do a : cons (x, a),
3095        a),
3096      block ([a : []],
3097        for x : 1 thru 5 while x < 3 do a : cons (x, a),
3098        a),
3099      block ([a : []],
3100        for x : 1 thru 5 while x > 3 do a : cons (x, a),
3101        a),
3102      block ([a : []],
3103        for x : 1 thru 5 while x < 10 do a : cons (x, a),
3104        a),
3105      block ([a : []],
3106        for x : 1 thru 5 while x > 10 do a : cons (x, a),
3107        a),
3108      block ([a : []],
3109        for x : 1 thru 5 unless x < 3 do a : cons (x, a),
3110        a),
3111      block ([a : []],
3112        for x : 1 thru 5 unless x > 3 do a : cons (x, a),
3113        a)],
3115   bar (p) :=
3116     [block ([a : []],
3117        for x : 1 thru 5 while p do a : cons (x, a),
3118        a),
3119      block ([a : []],
3120        for x : 1 thru 5 while x < 3 and p do a : cons (x, a),
3121        a),
3122      block ([a : []],
3123        for x : 1 thru 5 while x < 3 or p do a : cons (x, a),
3124        a),
3125      block ([a : []],
3126        for x : 1 thru 5 while x < 10 or 'z do a : cons (x, a),
3127        a)],
3129   baz () :=
3130     [block ([a : []],
3131        for x : 1 thru 5 do a : cons (if x then x else false, a),
3132        a),
3133      block ([a : []],
3134        for x : 1 thru 5 while x < 3 do a : cons (if x then x else false, a),
3135        a)],
3137   test () :=
3138     block ([res : []],
3139       push (foo (), res),
3140       for p in [true, false] do
3141         push (bar (p), res),
3142       push (baz (), res),
3143       push (errcatch (bar ('z)), res),
3144       res),
3146   l1 : test (),
3148   translate_or_lose (foo, bar, baz),
3150   l2 : test (),
3152   is (l1 = l2));
3153 true;
3155 (kill (foo, bar, baz), 0);
3158 /* Basic tests for error checking of translated return and go forms */
3160 (foo () := return (),
3161  translate (foo));
3164 (foo () := do return (1),
3165  translate_or_lose (foo),
3166  foo ());
3169 (foo () := block (return (2)),
3170  translate_or_lose (foo),
3171  foo ());
3174 (foo () := go (x),
3175  translate (foo));
3178 (foo () := block (go (f ())),
3179  translate (foo));
3182 /* *cough* */
3183 (foo () := do (go (1), return (false), 1, return (true)),
3184  translate_or_lose (foo),
3185  foo ());
3186 true;
3188 /* *cough* */
3189 (foo () := block (block (go (x)), return (1), go (x), return (2), x, 3),
3190  translate_or_lose (foo),
3191  foo ());
3194 (foo () := block (go (end), return (0), end, 1),
3195  translate_or_lose (foo),
3196  foo ());
3199 (kill (foo), 0);
3202 /* Bug #4260: translate fails with go tag in final position */
3204 block ([translate : false, l1, l2],
3205   foo () :=
3206     [block (),
3207      block ([]),
3208      block (1),
3209      block (a),
3210      block ('a),
3211      block (done),
3212      block ('done),
3213      block (go (0), return (false), 0),
3214      block (go (a), return (false), a),
3215      block (go (done), return (false), done),
3216      block (go (b), return (false), b, 1),
3217      block (go (c), return (false), c, d),
3218      block (go (f), return (false), f, 'g),
3219      block (go (done), return (false), done, 'end),
3220      block (go (2), return (false), 1, return (true), 2, go (1))],
3222   l1 : foo (),
3224   translate_or_lose (foo),
3226   l2 : foo (),
3228   is (l1 = l2));
3229 true;
3231 (kill (foo), 0);
3234 /* We had cases of incorrect number of argument evaluations when going
3235  * through MFUNCTION-CALL internally.
3236  */
3238 (eval_string_lisp ("
3239   (makunbound '$bar)
3240   (fmakunbound '$bar)
3241   (setf (symbol-plist '$bar) '())"),
3242  0);
3245 block ([translate : false, v1, v2],
3246   foo () := block ([n : 0], bar (n : n + 1)),
3248   v1 : foo (),
3250   translate_or_lose (foo),
3252   v2 : foo (),
3254   [v2, is (v1 = v2)]);
3255 [bar (1), true];
3257 (kill (foo), 0);
3260 block ([translate : false, v1, v2],
3261   local (bar),
3263   foo () := block ([n : 0], bar (n : n + 1)),
3265   bar (q) := q,
3267   v1 : foo (),
3269   translate_or_lose (foo),
3271   v2 : foo (),
3273   [v2, is (v1 = v2)]);
3274 [1, true];
3276 (kill (foo), 0);
3279 block ([translate : false, bar, v1, v2],
3280   foo () := block ([n : 0], bar (n : n + 1)),
3282   bar : lambda ([q], q),
3284   v1 : foo (),
3286   translate_or_lose (foo),
3288   v2 : foo (), /* this used to yield 2 */
3290   [v2, is (v1 = v2)]);
3291 [1, true];
3293 (kill (foo), 0);
3296 block ([translate : false, transrun : true, v1, v2],
3297   local (bar),
3299   foo () := block ([n : 0], bar (n : n + 1), n),
3301   translate_or_lose (foo),
3303   bar ('q) := 123,
3305   v1 : foo (), /* this used to yield 1 */
3307   transrun : false,
3309   v2 : foo (),
3311   [v1, is (v1 = v2)]);
3312 [0, true];
3314 (kill (foo), 0);
3317 block ([translate : false, transrun : true, v1, v2],
3318   foo () := block ([n : 0], bar (n : n + 1), n),
3320   translate_or_lose (foo),
3322   eval_string_lisp ("(defmspec $bar (q) (declare (ignore q)) 123)"),
3324   v1 : foo (), /* this used to yield 1 */
3326   transrun : false,
3328   v2 : foo (),
3330   [v1, is (v1 = v2)]);
3331 [0, true];
3333 (kill (foo, bar),
3334  eval_string_lisp ("(setf (symbol-plist '$bar) '())"),
3335  0);
3342 /*** KILLING THESE FUNCTIONS SHOULD BE THE LAST TEST IN THIS FILE ***/
3343 (kill (translate_or_lose, compile_or_lose), 0);
3345 /*** THERE SHOULD BE NO TESTS BEYOND THIS POINT ***/