Add ability to dump command line options in texi format
[maxima.git] / tests / rtest_translator.mac
blob4f7a9d6c8ebf0017b47de2563bedf60bbd918a6a
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), cos (x), cot (x), csc (x),
285       sinh (x), csch (x), sqrt (x), exp (x)]),
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,.8775825618903728,
295  1.830487721712452,2.085829642933488,.5210953054937474,1.919034751334944,
296  .7071067811865476,1.648721270700128]$
298 y1b : foo (1.5);
299 [.9051482536448664,14.10141994717172,.4250960349422805,14.1368329029699,
300  .9624236501192069*%i,.5880026035475675,.9974949866040544,.7297276562269662,
301  1.194763217287109,.6251451172504168,2.352409615243247,1.104791392982512,1.5,
302  .8410686705679303,1.570796326794897-.9624236501192069*%i,.9661051464753108,
303  .4054651081081644,0.0707372016677029,.07091484430265245,1.002511304246725,
304  2.129279455094817,.4696424405952246,1.224744871391589,4.481689070338065]$
306 y1c : foo (1.0);
307 [0.7615941559557649,1.557407724654902,0.6480542736638855,
308  1.850815717680925,0.0,0.7853981633974483,0.8414709848078965,
309  1.570796326794897,0.881373587019543,0.881373587019543,
310  1.543080634815244,1.313035285499331,1.0,0.0,1.570796326794897,
311  0.8427007929497148,0.0,0.5403023058681398,0.6420926159343306,
312  1.188395105778121,1.175201193643801,0.8509181282393216,1.0,
313  2.718281828459045]$
315 (translate_or_lose (foo), y2a : foo (0.5), y2b : foo (1.5), 0);
318 is (y1a = y2a);
319 true;
321 is (y1b = y2b);
322 true;
324 block ([tr_float_can_branch_complex : false],
325   translate_or_lose (foo),
326   y2c : foo (1.0),
327   0);
330 is (y1c = y2c);
331 true;
333 /* verify that save/compfile/compile_file/translate_file preserves upper/lower case in symbol names */
335 /* save */
337 (kill (all),
338  foo (x) := my_foo * x,
339  Foo (x) := my_Foo * x,
340  FOO (x) := my_FOO * x,
341  [my_foo, my_Foo, my_FOO] : [123, 456, 789],
342  results : [foo (2), Foo (3), FOO (4)],
343  my_test () := is (results = [2*123, 3*456, 4*789]),
344  lisp_name : ssubst ("_", " ", build_info()@lisp_name),
345  lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-save-", lisp_name, ".lisp"),
346  save (lisp_filename, values, functions),
347  kill (allbut (lisp_filename)),
348  load (lisp_filename),
349  my_test ());
350 true;
352 /* compfile */
354 (kill (all),
355  foo (x) := my_foo * x,
356  Foo (x) := my_Foo * x,
357  FOO (x) := my_FOO * x,
358  lisp_name : ssubst ("_", " ", build_info()@lisp_name),
359  lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compfile-", lisp_name, ".lisp"),
360  compfile (lisp_filename, functions),
361  kill (functions), 
362  load (lisp_filename),
363  [my_foo, my_Foo, my_FOO] : [123, 456, 789],
364  results : [foo (2), Foo (3), FOO (4)],
365  my_test () := is (results = [2*123, 3*456, 4*789]),
366  my_test ());
367 true;
369 /* compile_file */
371 /* skip this test (and fail) if Lisp = ECL because stream i/o causes "stack smashing" error
372  * see: https://sourceforge.net/p/maxima/bugs/3291/
373  */
374 if build_info()@lisp_name # "ECL" then
375 (kill (all),
376  lisp_name : ssubst ("_", " ", build_info()@lisp_name),
377  maxima_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compile_file-", lisp_name, ".mac"),
378  fasl_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compile_file-", lisp_name, ".fasl"),
379  lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compile_file-", lisp_name, ".LISP"),
380  maxima_output : openw (maxima_filename),
381  maxima_content :
382 "foo (x) := my_foo * x;
383 Foo (x) := my_Foo * x;
384 FOO (x) := my_FOO * x;
385 [my_foo, my_Foo, my_FOO] : [123, 456, 789];
386 results : [foo (2), Foo (3), FOO (4)];
387 my_test () := is (results = [2*123, 3*456, 4*789]);",
388  printf (maxima_output, maxima_content),
389  close (maxima_output),
390  compile_file (maxima_filename, fasl_filename, lisp_filename),
391  kill (allbut (lisp_filename)),
392  load (lisp_filename),
393  my_test ());
394 true;
396 /* translate_file */
398 /* skip this test (and fail) if Lisp = ECL because stream i/o causes "stack smashing" error
399  * see: https://sourceforge.net/p/maxima/bugs/3291/
400  */
401 if build_info()@lisp_name # "ECL" then
402 (kill (all),
403  lisp_name : ssubst ("_", " ", build_info()@lisp_name),
404  maxima_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-translate_file-", lisp_name, ".mac"),
405  lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-translate_file-", lisp_name, ".LISP"),
406  maxima_output : openw (maxima_filename),
407  maxima_content :
408 "foo (x) := my_foo * x;
409 Foo (x) := my_Foo * x;
410 FOO (x) := my_FOO * x;
411 [my_foo, my_Foo, my_FOO] : [123, 456, 789];
412 results : [foo (2), Foo (3), FOO (4)];
413 my_test () := is (results = [2*123, 3*456, 4*789]);",
414  printf (maxima_output, maxima_content),
415  close (maxima_output),
416  translate_file (maxima_filename, lisp_filename),
417  kill (allbut (lisp_filename)),
418  load (lisp_filename),
419  my_test ());
420 true;
422 /* Bug 2934:
424    Translating a literal exponent that comes out as a float shouldn't
425    produce assigned type any. This test runs the translation for a
426    trivial function that triggered the bug then looks in the unlisp
427    file (which contains messages from the translator) and checks that
428    there aren't any warnings.
430 /* skip this test (and fail) if Lisp = ECL because stream i/o causes "stack smashing" error
431  * see: https://sourceforge.net/p/maxima/bugs/3291/
432  */
433 if build_info()@lisp_name # "ECL" then
434 (kill (all),
435  lisp_name : ssubst ("_", " ", build_info()@lisp_name),
436  basename: sconcat (maxima_tempdir, "/tmp-rtest_translator-2934-", lisp_name),
437  maxima_filename : sconcat (basename, ".mac"),
438  lisp_filename : sconcat (basename, ".LISP"),
439  maxima_output : openw (maxima_filename),
440  maxima_content : "f () := block([y], mode_declare(y,float), y: 3^0.33, y)$",
441  printf (maxima_output, maxima_content),
442  close (maxima_output),
443  translate_file (maxima_filename, lisp_filename),
444  kill (allbut(basename)),
445  /* Any warning messages end up at .UNLISP */
446  block ([unlisp: openr (sconcat (basename, ".UNLISP")),
447          line, acc: []],
448    while stringp (line: readline(unlisp)) do
449      if is ("warning" = split(line, ":")[1]) then push(line, acc),
450    acc));
453 /* makelist translated incorrectly
454  * SF bug #3083: "Error on compiling a working maxima function"
455  */
457 (kill(all),
458  f1(n) := makelist (1, n),
459  f2(n) := makelist (i^2, i, n),
460  f3(l) := makelist (i^3, i, l),
461  f4(n) := makelist (i^4, i, 1, n),
462  f5(m, n) := makelist (i^5, i, 1, n, m),
463  translate_or_lose(f1, f2, f3, f4, f5),
464  0);
467 f1(5);
468 [1,1,1,1,1];
470 f2(5);
471 [1, 4, 9, 16, 25];
473 f3([1,2,3]);
474 [1, 8, 27];
476 f4(4);
477 [1, 16, 81, 256];
479 f5(2, 10);
480 [1, 243, 3125, 16807, 59049];
482 /* original function from bug report */
484 (ordersort(lis,vars,oper):=block([negsumdispflag:false,liss:lis,varlist:vars,temp], /*Does lexicographical sort */
485  for i:1 thru length(varlist) do (
486      for j:1 thru i do (
487          liss:sort(liss,lambda([x,y],apply("and",map(oper,makelist(part(x,2)[k],k,1,i)
488                              ,makelist(part(y,2)[k],k,1,i)))))
489      )),liss),
490  translate_or_lose (ordersort),
491  [member ('transfun, properties (ordersort)),
492   ordersort([[-7,[0,2,1]],[3,[1,2,1]],[1,[0,4,1]],[6,[4,3,3]],[6,[4,4,3]],
493              [-7,[3,5,4]],[2,[0,0,5]],[-10,[2,2,5]],[-10,[3,4,7]],[7,[3,8,9]]],
494              [x,y,z],
495              ">=")]);
496 [true,
497  [[6,[4,4,3]],[6,[4,3,3]],[7,[3,8,9]],[-7,[3,5,4]],[-10,[3,4,7]],
498   [-10,[2,2,5]],[3,[1,2,1]],[1,[0,4,1]],[-7,[0,2,1]],[2,[0,0,5]]]];
500 /* 'define' translated incorrectly, reported to mailing list circa 2017-01-24 */
502 (kill(foo, bar, baz, quux, mumble, blurf, umm, f, x, y),
503  foo(y) := define(bar(x), x + y),
504  baz(f, y) := define(funmake(f, [x]), x + y),
505  quux() := (mumble(x) := 1 + x),
506  [foo(10), baz(blurf, 20), quux()]);
507 /* note that results match because rhs of ":=" isn't simplified */
508 [bar(x) := 10 + x, blurf(x) := 20 + x, mumble(x) := 1 + x];
510 [bar(5), blurf(5), mumble(5)];
511 [15, 25, 6];
513 (kill(bar, blurf, mumble),
514  translate_or_lose(foo, baz, quux),
515  [foo(11), baz(umm, 21), quux()]);
516 /* note that results match because rhs of ":=" isn't simplified */
517 [bar(x) := 11 + x, umm(x) := 21 + x, mumble(x) := 1 + x];
519 makelist (is (x # false), x, map (?fboundp, [foo, baz, quux])); /* test for generalized Boolean value */
520 [true, true, true];
522 [bar(5), umm(5), mumble(5)];
523 [16, 26, 6];
525 /* mailing list 2017-03-04: "An example that is broken by compile()"
526  * translated code tickles a bug elsewhere (bug not in translator)
527  */
529 (kill(fun, trigfunc, t1),
530  fun():=block([trigfunc],
531         trigfunc:lambda([cur],cur>t1),
532         apply('trigfunc,[1])),
533  0);
536 /* I (Robert Dodier) believe this result should be trigfunc(1),
537  * but, in any event, interpreted and compiled code should agree.
538  * But if MAPPLY1 is ever changed, we can adjust these results.
539  */
540 fun();
541 1 > t1;
543 (compile_or_lose(fun), fun());
544 1 > t1;
546 (kill(fun, trigfunc, t1),
547  fun():=block([trigfunc],
548         trigfunc:lambda([cur],cur>t1),
549         apply(trigfunc,[1])),
550  0);
553 fun();
554 1 > t1;
556 (compile_or_lose(fun), fun());
557 1 > t1;
559 /* Verify that we catch malformed lambda expressions during translation.
560  * More checks need to be added to the translator and more tests need to
561  * be added here.
562  */
564 /* no parameter list */
565 (kill (f),
566  f () := lambda (),
567  translate (f))$
570 /* empty body */
571 (kill (f),
572  f () := lambda ([x]),
573  translate (f))$
576 /* non-symbol in parameter list */
577 (kill (f),
578  f () := lambda ([42], 'foo),
579  translate (f))$
582 /* misplaced "rest" parameter */
583 (kill (f),
584  f () := lambda ([[l], x], 'foo),
585  translate (f))$
588 /* invalid "rest" parameter */
589 (kill (f),
590  f () := lambda ([[l1, l2]], 'foo),
591  translate (f))$
594 /* attempting to bind a constant;
595  * now OK, after commit 0517895
596  */
597 block ([c, f],
598   local (c, f),
599   declare (c, constant),
600   f () := lambda ([c], c),
601   translate_or_lose (f))$
602 [f];
604 /* Verify that parameter/variable lists cannot contain duplicate variables.
606  * We only test a couple of cases here.  Many more tests for non-translated
607  * code are in rtest2.  Do we want to test them all here as well?
608  */
610 (kill(f),
611  f () := lambda ([x, [x]], x),
612  translate (f))$
615 (kill(f),
616  f () := block ([x, x:'foo], x),
617  translate (f))$
620 /* ensure that a null OPERATORS property doesn't interfere with
621  * translation of local variable used as a function name.
622  * This is the bug that caused failures in rtest_fractals when executed after run_testsuite.
623  */
625 (kill(aa, foobarbaz, mumbleblurf, hhh),
626  matchdeclare (aa, all),
627  tellsimp (mumbleblurf(aa), 1 - aa),
628  kill (mumbleblurf), /* as of 2018-01-28, this leaves (OPERATORS NIL) in property list */
629  hhh(mumbleblurf, u) := mumbleblurf(u),
630  foobarbaz(x) := 100 + x,
631  translate_or_lose (hhh),
632  hhh (foobarbaz, 11));
633 111;
635 /* SF bug report #3402: "Unbinding defined variable generates error in compiled functions" */
637 define_variable (zorble, 0, fixnum);
640 (kill(f), f() := block ([zorble], 42), f());
643 (translate_or_lose(f), f());
646 /* bug reported to mailing list 2018-12-03: "error in compiling function with global variable" */
648 (test_f():= block( [a,b,c,d], niceindicespref:[a,b,c,d], disp("ciao"), return() ),
649  0);
652 (test_f (), niceindicespref);
653 [a,b,c,d];
655 (reset (niceindicespref),
656  niceindicespref);
657 [i,j,k,l,m,n];
659 (translate_or_lose (test_f),
660  test_f (),
661  niceindicespref);
662 [a,b,c,d];
664 (reset (niceindicespref), 0);
667 /* additional tests with variables which have ASSIGN property */
669 (set_error_stuff_permanently () :=
670   block (error_syms : '[myerr1, myerr2, myerr3], error_size : 40),
671  set_error_stuff_temporarily() :=
672    block([error_syms : '[myerror1, myerror2, myerror3], error_size : 55],
673          [error_syms, error_size]),
674  0);
677 (reset (error_syms, error_size),
678  set_error_stuff_permanently (),
679  [error_syms, error_size]);
680 [[myerr1, myerr2, myerr3], 40];
682 (reset (error_syms, error_size),
683  translate_or_lose (set_error_stuff_permanently),
684  set_error_stuff_permanently (),
685  [error_syms, error_size]);
686 [[myerr1, myerr2, myerr3], 40];
688 (reset (error_syms, error_size),
689  set_error_stuff_temporarily());
690 [[myerror1, myerror2, myerror3], 55];
692 [error_syms, error_size];
693 [[errexp1, errexp2, errexp3], 60];
695 (translate_or_lose (set_error_stuff_temporarily),
696  set_error_stuff_temporarily());
697 [[myerror1, myerror2, myerror3], 55];
699 [error_syms, error_size];
700 [[errexp1, errexp2, errexp3], 60];
702 (kill(all), reset(), 0);
705 /* SF bug #3412: "Bug when translating functions that contain an \"if\" (in my case an implicit if)" */
706 /* Bug #4008: translator and prederror */
708 (f(x):=if cabs(1/(x+1)) < 1 then 1/(x+1) else 1,
709  f(x + %i*y));
710 if 1/sqrt(y^2+(x+1)^2) < 1 then 1/(%i*y+x+1) else 1;
712 makelist (f(xy[1] + %i*xy[2]), xy, [[0, 0], [0, 1], [1, 1], [1, 0], [0, 2], [2, 2], [2, 0]]);
713 [1, 1/(%i+1), 1/(%i+2), 1/2, 1/(2*%i+1), 1/(2*%i+3), 1/3]$
715 compile_or_lose (f);
716 [f];
718 block ([prederror : false],
719   f(x + %i*y));
720 if 1 - 1/sqrt(y^2+(x+1)^2) > 0 then 1/(%i*y+x+1) else 1;
722 block ([prederror : true],
723   errcatch (f(x + %i*y)));
726 '(f(x + %i*y));
727 f(x + %i*y);
729 makelist (f(xy[1] + %i*xy[2]), xy, [[0, 0], [0, 1], [1, 1], [1, 0], [0, 2], [2, 2], [2, 0]]);
730 [1, 1/(%i+1), 1/(%i+2), 1/2, 1/(2*%i+1), 1/(2*%i+3), 1/3]$
732 (if draw_version = 'draw_version then load (draw),
733  draw3d(contour='map,
734         proportional_axes=xy,
735         nticks=100,
736         contour_levels=20,
737         explicit('(f(x+%i*y)),x,-2,2,y,-2,2)),
738  0);
741 /* nested if example -- note top-level "if" doesn't have an "else" clause, so the result is sometimes 'false' */
743 (g(a, b, c) := if a + b > c
744                  then (if a > c
745                          then (if b > c
746                                  then (a + b + c)
747                                  elseif b > c/2
748                                    then (a - b - c)
749                                    else (b - a - c))
750                          else (a/2)),
751  0);
754 (aa: [3,9/4,5/4,11/4,1,0,9/4,1/4,5/2,9/4,3,5/2],
755  bb: [3/2,3,1/4,3/4,5/2,7/4,5/2,3/4,1/2,3,13/4,7/2],
756  cc: [7/2,15/4,5/2,5/4,15/4,1,1/4,7/4,2,11/4,1/4,7/4],
757  map (g, aa, bb, cc));
758 [3/2,9/8,false,3/4,false,0,5,false,-4,9/8,13/2,31/4]$
760 (translate_or_lose (g),
761  map (g, aa, bb, cc));
762 [3/2,9/8,false,3/4,false,0,5,false,-4,9/8,13/2,31/4]$
764 block ([prederror : false],
765   g (1, 1, z));
766 ''(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));
768 block ([prederror : true],
769   errcatch (g (1, 1, z)));
772 /* SF bug #3556: "5.43.0 translate / compile error"
773  * Ensure that "if" within lambda is translated correctly.
774  * The fix for #3412 tickled this bug.
775  */
777 (kill (f),
778  f(x, m) := map (lambda ([u], if m > 0 then u^m), [x, 2*x, 3*x]),
779  0);
782 is (?fboundp (f) # false);
783 false;
785 (kill (y),
786  [f(y, 2), f(y, -2)]);
787 [[y^2, 4*y^2, 9*y^2], [false, false, false]];
789 (kill (n),
790  errcatch (f(10, n)));
791 /* ensure that conditional expressions get simplified to expunge $FALSE ... sigh. */
792 ''([[if n > 0 then 10^n, if n > 0 then 20^n, if n > 0 then 30^n]]);
794 (translate_or_lose (f),
795  is (?fboundp (f) # false)); /* test for generalized Boolean value */
796 true;
798 [f(y, 2), f(y, -2)];
799 [[y^2, 4*y^2, 9*y^2], [false, false, false]];
801 block ([prederror : false],
802   f(10, n));
803 ''([if n > 0 then 10^n, if n > 0 then 20^n, if n > 0 then 30^n]);
805 block ([prederror : true],
806   errcatch (f(10, n)));
809 /* apply2 was translated incorrectly for several years.  applyb2
810  * was translated incorrectly for decades.
811  */
813 (defrule (foorule, foo (), 1),
814  f () := apply2 ('(foo ()), foorule),
815  translate_or_lose (f),
816  f ());
819 (defrule (barrule, bar (), 2),
820  g () := applyb2 ('(bar ()), barrule),
821  translate_or_lose (g),
822  g ());
825 (kill (foorule, f, barrule, g), 0);
828 /* atan and atan2 calls with float arguments were translated
829  * incorrectly for over a decade.  atan always caused a lisp error
830  * and atan2 had a range between 0 and 2*%pi that was inconsistent
831  * with the interpreted and non-float cases (where the range is
832  * between -%pi and %pi).
833  */
835 (foo () := [atan2 (-1.0, -1.0), atan2 (-1.0, 1.0)],
836  translate_or_lose (foo),
837  foo ());
838 [-2.356194490192345, -0.7853981633974483];
840 (bar () := atan (-1.0),
841  translate_or_lose (bar),
842  bar ());
843 -0.7853981633974483;
845 (kill (foo, bar), 0);
848 /* The translation of a signum call with a float argument was
849  * inconsistent when compared to the interpreted case and other
850  * translated cases.  signum should return an integer or a float
851  * when given an integer or a float argument, respectively.
852  */
854 (foo () := [signum (0),  signum (0.0),
855             signum (2),  signum (2.0),
856             signum (-3), signum (-3.0)],
857  translate_or_lose (foo),
858  foo ());
859 [0, 0.0, 1, 1.0, -1, -1.0];
861 (kill (foo), 0);
864 /* The translation of declare was broken for decades.  It worked
865  * under Maclisp, but it had never worked under Common Lisp.
866  */
868 (foo () := declare (n, integer, [x, y], noninteger),
869  translate_or_lose (foo),
870  foo (),
871  [?kindp (n, integer),
872   ?kindp (n, noninteger),
873   ?kindp (x, integer),
874   ?kindp (x, noninteger),
875   ?kindp (y, integer),
876   ?kindp (y, noninteger)]);
877 [true, false, false, true, false, true];
879 (kill (foo, n, x, y), 0);
882 /* If a variable was declared to be of mode rational, then a lisp
883  * error could occur during translation when attempting to convert
884  * it to a float.
885  */
887 (foo (x) := (mode_declare (x, rational), float (x)),
888  bar (y) := (mode_declare (y, rational), 1.0 + y),
889  translate_or_lose (foo, bar),
890  [foo (1/4), bar (1/2)]);
891 [0.25, 1.5];
893 (kill (foo, bar, x, y), 0);
896 /* The translation of an atan2 call with one float and one rational
897  * argument was broken because the rational was not converted to a
898  * float before calling ATAN.
899  */
901 (foo () :=
902    [atan2 (0.0, -1/2),
903     atan2 (-1/2, 0.0),
904     atan2 (0.0, -1),
905     atan2 (1, 0.0)],
906  bar (y, x) := (mode_declare (x, float, y, rational), atan2 (y, x)),
907  l1 : [foo (), bar (1/3, 0.0)],
908  translate_or_lose (foo, bar),
909  l2 : [foo (), bar (1/3, 0.0)],
910  is (l1 = l2));
911 true;
913 (kill (foo, bar, x, y, l1, l2), 0);
916 /* When attempting to apply float contagion to the arguments, some
917  * translations of max and min with mixed float and rational arguments
918  * were broken because the rationals were not converted to floats before
919  * calling MAX or MIN (like atan2 above).  Also, due to implementation-
920  * dependent behavior in the underlying lisp regarding what to return
921  * from MAX and MIN, the wrong mode could be used during translation and
922  * some of the translations were possibly inconsistent with interpreted
923  * cases.
924  */
926 (foo (x) :=
927    (mode_declare (x, rational),
928     [max (),         min (),
929      max (1),        min (1),
930      max (1.0),      min (1.0),
931      max (9/10),     min (9/10),
932      max (x)   ,     min (x),
933      max (0.0, 1),   min (0.0, 1),
934      max (0, 1),     min (0, 1),
935      max (1.0, 1),   min (1.0, 1),
936      max (1, 1.0),   min (1, 1.0),
937      max (2.0, 3.0), min (2.0, 3.0),
938      max (-1, 1/2),  min (-1, 1/2),
939      max (3/4, 1/2), min (3/4, 1/2),
940      max (0.0, 1/2), min (0.0, 1/2),
941      max (0, x),     min (0, x),
942      max (-1.0, x),  min (-1.0, x),
943      max (5/6, x),   min (5/6, x),
944      max (x, 1),     min (x, 1)]),
945  l1 : foo (2/3),
946  translate_or_lose (foo),
947  l2 : foo (2/3),
948  is (l1 = l2));
949 true;
951 (kill (foo, x, l1, l2), 0);
954 /* log and sqrt did not honor tr_float_can_branch_complex */
956 (foo (x) :=
957    (mode_declare (x, float),
958     [log  (-1.0), log  (x),
959      sqrt (-1.0), sqrt (x)]),
960  /* l1 is a list of Maxima complex numbers */
961  l1 : foo (-2.0),
962  some (lambda ([x], freeof (%i, x)), l1));
963 false;
965 block ([tr_float_can_branch_complex : false],
966   translate_or_lose (foo),
967   /* l2 is a list of lisp complex numbers because we told the
968    * translator to assume the return values of log and sqrt
969    * would not be complex, and it correctly returned the complex
970    * numbers returned by LOG and SQRT directly.
971    */
972   l2 : foo (-2.0),
973   [every (?complexp, l2),
974    every ("#", l1, l2)]);
975 [true,
976  true];
978 block ([tr_float_can_branch_complex : true],
979   translate_or_lose (foo),
980   /* l3 is a list of Maxima complex numbers because we told the
981    * translator to assume the return values of log and sqrt
982    * could be complex, and it converted the lisp complex numbers
983    * returned by LOG and SQRT to Maxima complex numbers.
984    */
985   l3 : foo (-2.0),
986   every (lambda ([x, y], cabs (x - y) < 1e-15), l1, l3));
987 true;
989 (kill (foo, x, l1, l2, l3), 0);
992 /* The translations for evaluating = and # expressions to boolean
993  * values with one float argument and a different numerical argument
994  * (e.g. a fixnum) gave bogus results because the translator was
995  * incorrectly applying float contagion to the arguments.
996  */
998 (foo (s, w, x, y, z) :=
999   (mode_declare (w, number, x, fixnum, y, flonum),
1000    [/* These translate to EQL comparisons */
1001     is (1 = 1),                 is (1 # 1),
1002     is (1 = 1.0),               is (1 # 1.0),
1003     is (1 = float (1)),         is (1 # float (1)),
1004     is (1.0 = float (1)),       is (1.0 # float (1)),
1005     is (w = 2),                 is (w # 2),
1006     is (w = 2.0),               is (w # 2.0),
1007     is (x = 3),                 is (x # 3),
1008     is (x = 3.0),               is (x # 3.0),
1009     is (x = float (3)),         is (x # float (3)),
1010     is (x = float (x)),         is (x # float (x)),
1011     is (y = 4),                 is (y # 4),
1012     is (y = 4.0),               is (y # 4.0),
1013     is (y = float (4)),         is (y # float (4)),
1014     is (y = float (y)),         is (y # float (y)),
1015     /* These translate to LIKE comparisons */
1016     is (z = 5),                 is (z # 5),
1017     is (z = 5.0),               is (z # 5.0),
1018     is (z = float (5)),         is (z # float (5)),
1019     is (z = float (z)),         is (z # float (z)),
1020     is (1/2 = 1/2),             is (1/2 # 1/2),
1021     is (1/2 = rat (1/2)),       is (1/2 # rat (1/2)),
1022     is (rat (1/2) = rat (1/2)), is (rat (1/2) # rat (1/2)),
1023     is (1/2 = 0.5),             is (1/2 # 0.5),
1024     is (1/2 = float (1/2)),     is (1/2 # float (1/2)),
1025     is (%i = %i),               is (%i # %i),
1026     is (1 + %i = 1 + %i),       is (1 + %i # 1 + %i),
1027     is (s = s),                 is (s # s),
1028     is (s = 'bar),              is (s # 'bar),
1029     is (s = 1),                 is (s # 1),
1030     is (s = 1.0),               is (s # 1.0),
1031     is (s = 1/2),               is (s # 1/2),
1032     is ('f (0) = 'f (0)),       is ('f (0) # 'f (0)),
1033     is ('g (s) = 'g (s)),       is ('g (s) # 'g (s)),
1034     is ('h (w) = 'h (w)),       is ('h (w) # 'h (w)),
1035     is ('i (x) = 'i (x)),       is ('i (x) # 'i (x)),
1036     is ('j (y) = 'j (y)),       is ('j (y) # 'j (y)),
1037     is ('k (z) = 'k (z)),       is ('k (z) # 'k (z))]),
1038  l1 : foo ('bar, 2, 3, 4.0, 5),
1039  translate_or_lose (foo),
1040  l2 : foo ('bar, 2, 3, 4.0, 5),
1041  [every (lambda ([x], ?typep (x, ?boolean)), l2),
1042   is (l1 = l2)]);
1043 [true,
1044  true];
1046 (kill (foo, w, x, y, l1, l2), 0);
1049 /* Bug #3048: notequal is not translated properly
1051  * notequal expressions were only generically translated like user
1052  * function calls and the use of notequal in translated code caused
1053  * a runtime warning about it being totally undefined.  Also the
1054  * evaluation of notequal expressions to boolean values (via is, if,
1055  * etc.) were translated like the evaluation of an unknown predicate.
1056  */
1058 (assume (equal (a, b), notequal (c, d)),
1059  foo () :=
1060   [is (equal (1, 1)),
1061    is (notequal (1, 1)),
1062    is (equal (1, 1.0)),
1063    is (notequal (1, 1.0)),
1064    is (equal (1, 1.0b0)),
1065    is (notequal (1, 1.0b0)),
1066    is (equal (1/2, 0.5)),
1067    is (notequal (1/2, 0.5)),
1068    is (equal (1/2, 0.5b0)),
1069    is (notequal (1/2, 0.5b0)),
1070    is (equal (1, 2)),
1071    is (notequal (1, 2)),
1072    is (equal ('ind, 'ind)),
1073    is (notequal ('ind, 'ind)),
1074    is (equal ('und, 'und)),
1075    is (notequal ('und, 'und)),
1076    is (equal ('a, 'b)),
1077    is (notequal ('a, 'b)),
1078    is (equal ('c, 'd)),
1079    is (notequal ('c, 'd)),
1080    is (equal (x^2 - 1, (x + 1) * (x - 1))),
1081    is (notequal (x^2 - 1, (x + 1) * (x - 1)))],
1082  l1 : foo (),
1083  translate_or_lose (foo),
1084  l2 : foo (),
1085  [every (lambda ([x], ?typep (x, ?boolean)), l2),
1086   is (l1 = l2)]);
1087 [true,
1088  true];
1090 (kill (foo, l1, l2),
1091  forget (equal (a, b), notequal (c, d)),
1092  0);
1095 /* The translation of a call to random with a float argument could
1096  * cause the generation of bogus code because this always had the
1097  * mode of fixnum.
1098  */
1100 (foo (w, x, y, z) :=
1101   (mode_declare (w, fixnum, x, float),
1102    [[random (10),
1103      random (w),
1104      random (y)],
1105     [random (1.0),
1106      random (x),
1107      random (z),
1108      random (x) / 2,
1109      random (z) / 2,
1110      1 / (1 + random (x))],
1111     [random (10) / 2,
1112      random (w) / 3,
1113      random (y) / 4,
1114      1 / (1 + random (w)),
1115      1 / (1 + random (y))]]),
1116  translate_or_lose (foo),
1117  l : foo (50, 5.0, 100, 10.0),
1118  [every (integerp, first (l)),
1119   every (floatnump, second (l)),
1120   every (ratnump, third (l))]);
1121 [true,
1122  true,
1123  true];
1125 (kill (foo, w, x, l), 0);
1128 /* acosh, asech, atanh and acoth now have special translations for
1129  * float arguments.  These all honor tr_float_can_branch_complex.
1130  */
1132 (foo (x) :=
1133    (mode_declare (x, float),
1134     [acosh (x), asech (x), atanh (x)]),
1135  bar (x) :=
1136    (mode_declare (x, float),
1137     [acoth (x)]),
1138  /* l1 is a list of Maxima complex numbers */
1139  l1 : append (foo (-3.0), foo (-2.0), bar (-0.5), bar (0.5)),
1140  some (lambda ([x], freeof (%i, x)), l1));
1141 false;
1143 block ([tr_float_can_branch_complex : false],
1144   translate_or_lose (foo, bar),
1145   /* l2 is a list of lisp complex numbers because we told the
1146    * translator to assume the return values would not be complex,
1147    * and it correctly returned the lisp complex numbers directly.
1148    */
1149   l2 : append (foo (-3.0), foo (-2.0), bar (-0.5), bar (0.5)),
1150   [every (?complexp, l2),
1151    every ("#", l1, l2),
1152    every ("=", l1, map (?complexify, l2))]);
1153 [true,
1154  true,
1155  true];
1157 block ([tr_float_can_branch_complex : true],
1158   translate_or_lose (foo, bar),
1159   /* l3 is a list of Maxima complex numbers because we told the
1160    * translator to assume the return values could be complex, and
1161    * it converted the lisp complex numbers to Maxima complex numbers.
1162    */
1163   l3 : append (foo (-3.0), foo (-2.0), bar (-0.5), bar (0.5)),
1164   every ("=", l1, l3));
1165 true;
1167 (kill (foo, bar, x, l1, l2, l3), 0);
1170 /* Bug #3642: Lisp error when translating assume
1172  * Translating an assume call with an atomic argument would cause a
1173  * lisp error during translation.
1174  */
1176 (foo () :=
1177    block ([ctx : supcontext (),
1178            x : a > 0,
1179            y : b > 0,
1180            r],
1181      assume (x, y, equal (c, 0)),
1182      r : [is (a > 0), is (b < 0), is (equal (c, 0))],
1183      killcontext (ctx),
1184      r),
1185  translate_or_lose (foo),
1186  foo ());
1187 [true, false, true];
1189 (kill (foo), 0);
1192 /* The translation of errcatch was broken because the mode of the
1193  * whole form was always assumed to be the same as the mode of the
1194  * last subform.  Since errcatch always yields a list, lisp errors
1195  * could easily occur.
1196  */
1198 (foo () :=
1199    block ([listarith : true],
1200      [errcatch (1),
1201       1 + errcatch (2),
1202       1.0 * errcatch (2.0),
1203       errcatch (error ("oops")),
1204       errcatch (?error ("oops")),
1205       errcatch (1 / 0)]),
1206  translate_or_lose (foo),
1207  foo ());
1208 [[1],
1209  [3],
1210  [2.0],
1211  [],
1212  [],
1213  []];
1215 (kill (foo), 0);
1218 /* Attempting to translate multiple functions containing local would
1219  * cause an error.  Similarly, translating the same function multiple
1220  * times would cause an error if that function contained local.
1221  */
1223 (foo () := local (), /* just something with local (not within a block) */
1224  bar () := local (), /* something else with local (not within a block) */
1225  translate_or_lose (foo),
1226  translate_or_lose (bar),
1227  translate_or_lose (foo, bar));
1228 [foo, bar];
1230 (kill (foo, bar), 0);
1233 /* Bug #2976: "local" doesn't work in translated code
1235  * For decades no attempt was being made to clean up any local
1236  * properties.
1237  */
1239 /* The internal LOCLIST used by local should be empty right now */
1240 ?null (?loclist);
1241 true;
1243 (f0 () := "one",
1244  foo1 () :=
1245    (local (f0),
1246     f0 () := "two",
1247     f0 ()),
1248  translate_or_lose (foo1),
1249  block ([v : foo1 ()],
1250    [f0 (), v]));
1251 ["one", "two"];
1253 (kill (f0, foo1), 0);
1256 (arr1 [0] : "three",
1257  foo2 () :=
1258    block ([g : lambda ([],
1259                  local (arr1, arr2),
1260                  arr1 [0] : "four",
1261                  arr2 [5] : "five",
1262                  [arr1 [0],
1263                   arr2 [5],
1264                   arrayinfo (arr2)])],
1265      apply (g, [])),
1266  translate_or_lose (foo2),
1267  block ([v : foo2 ()],
1268    [arr1 [0],
1269     v,
1270     errcatch (arrayinfo (arr2))]));
1271 ["three",
1272  ["four",
1273   "five",
1274   [hashed, 1, [5]]],
1275  []];
1277 (kill (arr1, foo2), 0);
1280 (foo3 (n) :=
1281    (local (h),
1282     h () := n + 1,
1283     if n = 10 then
1284       n
1285     else
1286       foo3 (h ())),
1287  translate_or_lose (foo3),
1288  foo3 (0));
1291 (kill (foo3), 0);
1294 /* The internal LOCLIST used by local should be empty right now */
1295 ?null (?loclist);
1296 true;
1298 /* The fpprintprec itself is not important in this test.  I'm
1299  * just picking something that has an ASSIGN property because
1300  * that's a separate internal case in the translator.
1302  * This test is ugly, but it's testing different cases and
1303  * their interactions.
1304  */
1305 block ([v],
1306   local (f1, f2, arr),
1307   f1 () := 0,
1308   f2 () := 123,
1309   arr [1] : "a",
1310   bar (fpprintprec) :=
1311     (local (f1, arr),
1312      fpprintprec : 5,
1313      f1 () := 42,
1314      arr [1] : "b",
1315      [block (
1316         local (f2, arr),
1317         f2 () := 69,
1318         arr [1] : "c",
1319         [f1 (), f2 (), arr [1]]),
1320       [f1 (), f2 (), arr [1]]]),
1321   translate_or_lose (bar),
1322   v : bar (3),
1323   [is (?get ('fpprintprec, '?assign) = false),
1324    v,
1325    [f1 (), f2 (), arr [1]]]);
1326 [false,
1327  [[42, 69, "c"],
1328   [42, 123, "b"]],
1329  [0, 123, "a"]];
1331 (kill (bar), 0);
1334 /* This is testing to make sure there are no bad interactions
1335  * between the usual local cleanup and errcatch cleanup (this
1336  * also mixes the interpreted and translated cases).  This test
1337  * is also ugly.
1339  * The original implementation of local properties (from decades
1340  * ago) not only failed to clean up local properties at all, but
1341  * it wasn't even setting up the internal state to keep up with
1342  * these properties correctly.  An initial attempt at fixing bug
1343  * #2976 made this problem clear because with that it was easy to
1344  * cause an infinite loop during certain things like errcatch
1345  * cleanup.
1346  */
1347 block ([translate : false,
1348         vi, vt],
1349   local (f3),
1350   f3 () := -10,
1351   baz1 () :=
1352     (error ("oops 1"),
1353      local (f4),
1354      f4 () := 0),
1355   baz2 () :=
1356     (local (f5),
1357      f5 () := 1,
1358      error ("oops 2")),
1359   translate_or_lose (baz1, baz2),
1360   baz_test () :=
1361     [block (
1362        local (f3),
1363        f3 () := -1,
1364        errcatch (baz1 ()),
1365        f3 ()),
1366      block (
1367        local (f3),
1368        f3 () := -2,
1369        errcatch (baz2 ()),
1370        f3 ())],
1371   vi : baz_test (),
1372   translate_or_lose (baz_test),
1373   vt : baz_test (),
1374   [vi,
1375    vt,
1376    is (f3 () = -10),
1377    is (f4 () = 0),
1378    is (f5 () = 1)]);
1379 [[-1, -2],
1380  [-1, -2],
1381  true,
1382  false,
1383  false];
1385 /* The internal LOCLIST used by local should be empty right now */
1386 ?null (?loclist);
1387 true;
1389 (kill (baz1, baz2, baz_test), 0);
1392 /***** This ends the bug #2976 tests *****/
1394 /* compile wasn't always compiling the correct function
1396  * This test not only depends on the internal details of how certain
1397  * functions are currently translated, but it also depends on internal
1398  * details about how DEFMFUN defines functions.  This also doesn't
1399  * really test that the correct function gets compiled because the
1400  * lisp implementation could have just compiled it itself anyway.  Ugh.
1401  */
1403 (foo () := 1,
1404  compile_or_lose (foo),
1405  ?compiled\-function\-p (?symbol\-function (?get (foo, ?impl\-name))));
1406 true;
1408 (kill (foo), 0);
1411 /* Some internal function definitions and compiler macros were not
1412  * being cleaned up, and this could cause confusing and bogus results
1413  * when an outdated compiler macro was being used.
1415  * Specifically one problem we had involved translating a function,
1416  * redefining it and then translating the new definition.  The internal
1417  * function and compiler macro from the original function could be used
1418  * when compiling calls to the new function if they were not overwritten.
1420  * This all depended on lisp implementation-dependent behavior because
1421  * implementations are not required to ever use compiler macros.  Ugh.
1423  * This test also depends on internal details of how certain functions
1424  * are currently translated.  Double ugh.
1425  */
1427 (foo () := 0,
1428  translate_or_lose (foo),
1429  kill (foo),
1430  foo ([l]) := l,
1431  translate_or_lose (foo),
1432  test1 () := foo (),
1433  test2 () := foo (1, 2, 3),
1434  compile_or_lose (test1, test2),
1435  /* Previously we observed test1 returning 0 and test2 causing a lisp
1436   * error because the compiler macro and old internal function from
1437   * the first foo were being used.
1438   */
1439  [test1 (), test2 ()]);
1440 [[], [1, 2, 3]];
1442 (kill (foo, test1, test2), 0);
1445 /* https://stackoverflow.com/questions/64631208/compilation-global-variables-with-warning
1447  * First verify that error_syms and niceindicespref assignments work as expected.
1448  */
1450 kill (aa, bb, cc);
1451 done;
1453 errcatch (error_syms: 123);
1456 errcatch (error_syms: [aa, bb, 123]);
1459 error_syms: [aa, bb, cc];
1460 [aa, bb, cc];
1462 errcatch (niceindicespref: 123);
1465 errcatch (niceindicespref: []);
1468 niceindicespref: [aa, bb, cc];
1469 [aa, bb, cc];
1471 (reset (error_syms, niceindicespref), 0);
1474 /* now the example from the Stackoverflow question */
1476 (program_content:
1477 "define_variable(foo, true, boolean)$
1478 foo: true$
1480 exprp(that) := if foo = false and listp(that) and not emptyp(that) and member(that[1], [\"+\", \"*\"]) then(foo: true, true)$
1481 matchdeclare(exprm, exprp)$
1482 defrule(rule_1, exprm, subst(exprm[1], \"[\", exprm[2]))$
1484 calc(list) := block([steps: []],
1485 while foo do(
1486     steps: endcons(list, steps),
1487     foo: false,
1488     list: applyb1(list, rule_1)
1490 steps
1493 calc_result: calc([\"+\", [[\"*\", [1, 2, 3]], [\"+\", [3, 4, 6]]]]);",
1494 program_file_name: sconcat (maxima_tempdir, "/tmp_program.mac"),
1495 with_stdout (program_file_name, print (program_content)),
1499 kill (calc_result);
1500 done;
1502 ([file_name_original, file_name_LISP, file_name_UNLISP, file_name_compiled]: compile_file (program_file_name), 0);
1505 stringp (file_name_compiled);
1506 true;
1508 calc_result;
1509 calc_result;
1511 (load (file_name_compiled),
1512  calc_result);
1513 [["+", [["*", [1, 2, 3]], ["+", [3, 4, 6]]]],
1514  ["+", [6, ["+", [3, 4, 6]]]],
1515  ["+", [6, 13]],
1516  19];
1518 (kill (program_content, program_file_name, file_name_original, file_name_LISP, file_name_UNLISP, file_name_compiled, calc_result), 0);
1522 /* Some additional basic tests for functions with rest args */
1524 block ([translate : false],
1525   foo ([r]) := r,
1526   bar (a, b, [c]) := [a, b, c],
1527   test () :=
1528     [foo (),
1529      foo (1),
1530      foo (1, 2, 3),
1531      errcatch (bar ()),
1532      errcatch (bar (1)),
1533      bar (1, 2),
1534      bar (1, 2, 3),
1535      bar (1, 2, 3, 4, 5)],
1537   /* l1: foo, bar and test are interpreted */
1538   l1 : test (),
1540   /* l2: foo and bar are translated, and test is interpreted */
1541   translate_or_lose (foo, bar),
1542   l2 : test (),
1544   /* l3: foo, bar and test are translated */
1545   translate_or_lose (test),
1546   l3 : test (),
1548   [is (l1 = l2),
1549    is (l2 = l3),
1550    l1]);
1551 [true,
1552  true,
1553  [[],
1554   [1],
1555   [1, 2, 3],
1556   [],
1557   [],
1558   [1, 2, []],
1559   [1, 2, [3]],
1560   [1, 2, [3, 4, 5]]]];
1562 (kill (foo, bar, test, l1, l2, l3), 0);
1565 /* Attempting to translate a macro with a rest arg always caused an
1566  * error during translation because the translator was constructing
1567  * bogus Maclisp-style lexpr lambda expressions.
1568  */
1570 block ([translate : false],
1571   foo ([r]) ::=
1572     buildq ([r], ['r, r]),
1573   bar (a, b, [c]) ::=
1574     buildq ([a, b, c], ['a, a, 'b, b, 'c, c]),
1575   test1 () :=
1576     block ([x : 1, z : 3],
1577       [foo (),
1578        foo (x),
1579        foo (x, y, z),
1580        bar (x, y),
1581        bar (x, y, z),
1582        bar (x, y, z, 4, 5, 6)]),
1583   /* test2 cannot be translated due to the WNA error during macro
1584    * expansion, but we can call and test it in the interpreter
1585    */
1586   test2 () :=
1587     [errcatch (bar ()),
1588      errcatch (bar (1))],
1590   /* l1: foo, bar and test1 are interpreted */
1591   l1 : test1 (),
1593   /* l2: foo and bar are translated, and test1 is interpreted */
1594   translate_or_lose (foo, bar),
1595   l2 : test1 (),
1597   /* l3: foo, bar and test1 are translated */
1598   translate_or_lose (test1),
1599   l3 : test1 (),
1601   [test2 (),
1602    is (l1 = l2),
1603    is (l2 = l3),
1604    l1]);
1605 [[[], []],
1606  true,
1607  true,
1608  [[[], []],
1609   [['x], [1]],
1610   [['x, 'y, 'z], [1, 'y, 3]],
1611   ['x, 1, 'y, 'y, [], []],
1612   ['x, 1, 'y, 'y, ['z], [3]],
1613   ['x, 1, 'y, 'y, ['z, 4, 5, 6], [3, 4, 5, 6]]]];
1615 (kill (foo, bar, test1, test2, l1, l2, l3), 0);
1618 /* Some additional basic tests for conditionals.
1620  * We test both elseif and else-if ("else if").
1621  */
1623 block ([translate : false],
1624   mysignum1 (x) := if x > 0 then 1 elseif  x < 0 then -1 else 0,
1625   mysignum2 (x) := if x > 0 then 1 else if x < 0 then -1 else 0,
1626   foo () :=
1627     [if true then 1,
1628      if false then 1,
1629      if true then 1 else 2,
1630      if false then 1 else 2,
1631      if 1 < 2 then 'y,
1632      if 1 < 2 then 'y else 'n,
1633      if 1 > 2 then 'n,
1634      if 1 > 2 then 'n else 'y,
1635      if 1 > 2 then 'n elseif  1 = 2 then 'n else 'y,
1636      if 1 > 2 then 'n else if 1 = 2 then 'n else 'y,
1637      mysignum1 (-3),
1638      mysignum2 (-3),
1639      mysignum1 (0),
1640      mysignum2 (0),
1641      mysignum1 (2),
1642      mysignum2 (2)],
1643   l1 : foo (),
1644   translate_or_lose (mysignum1, mysignum2, foo),
1645   l2 : foo (),
1646   [is (l1 = l2),
1647    l2]);
1648 [true,
1649  [1, false, 1, 2, 'y, 'y, false, 'y, 'y, 'y, -1, -1, 0, 0, 1, 1]];
1651 (kill (mysignum1, mysignum2, foo, l1, l2), 0);
1654 /* Bogus translations of nested conditionals in elseif clauses
1656  * The translation of a conditional with another conditional nested
1657  * directly under an elseif clause was totally wrong.  Using else-if
1658  * ("else if") instead of elseif would work fine.
1661  * We use the with_both_elseifs macro so we can test both elseif and
1662  * else-if without having to duplicate portions of the tests below.
1663  * Give this macro a conditional expression with elseifs and it will
1664  * expand into a list: the first element is the same expression given
1665  * to it (with elseifs), and the second element is that same expression
1666  * rewritten to use else-ifs instead of elseifs.
1667  */
1669 (to_else_if (expr) :=
1670    if mapatom (expr) then
1671      expr
1672    else
1673      block ([op : op (expr), args : args (expr)],
1674        if op = "if" and length (args) > 4 then
1675          funmake (op, map ('to_else_if, append (firstn (args, 2), [true, funmake (op, rest (args, 2))])))
1676        else
1677          funmake (op, map ('to_else_if, args))),
1678  with_both_elseifs (expr) ::=
1679    buildq ([expr, texpr : to_else_if (expr)],
1680      [expr, texpr]),
1681   0);
1684 block ([translate : false],
1685   foo () :=
1686     with_both_elseifs (
1687       if false then
1688         'lose1
1689       elseif false then
1690         'lose2
1691       elseif false then
1692         if true then
1693           'lose3
1694         else
1695           'lose4
1696       else
1697         'win),
1699   /* l1: foo is interpreted */
1700   l1 : foo (),
1702   translate_or_lose (foo),
1704   /* l2: foo is translated
1705    *
1706    * foo used to give lose3 instead of win in the elseif case.
1707    */
1708   l2 : foo (),
1710   [is (l1 = l2),
1711    l2]);
1712 [true,
1713  ['win, 'win]];
1715 block ([translate : false],
1716   /* There is nothing special about bar here.  This is just some
1717    * function that has several branches with nested conditionals.
1718    */
1719   bar (x) :=
1720     with_both_elseifs (
1721       if x > 5 then
1722         if x > 7 then
1723           'more_than_seven
1724         elseif x > 6 then
1725           'seven
1726         else
1727           'six
1728       elseif x > 2 then
1729         if x > 4 then
1730           'five
1731         elseif x > 3 then
1732           'four
1733         else
1734           'three
1735       elseif x >= 0 then
1736         if x > 1 then
1737           'two
1738         elseif x > 0 then
1739           'one
1740         else
1741           'zero
1742       else
1743         'negative),
1745   /* We test bar with the integers -2 to 9 */
1746   inputs : makelist (k, k, -2, 9),
1748   /* l1: bar is interpreted */
1749   l1 : map (bar, inputs),
1751   translate_or_lose (bar),
1753   /* l2: bar is translated
1754    *
1755    * bar used to give incorrect results in the elseif case for every
1756    * number less than or equal to 2 (which means we got incorrect
1757    * results for the integers -2 to 2 in this test).
1758    */
1759   l2 : map (bar, inputs),
1761   [is (l2 = l1),
1762    l2]);
1763 [true,
1764  [['negative, 'negative],
1765   ['negative, 'negative],
1766   ['zero, 'zero],
1767   ['one, 'one],
1768   ['two, 'two],
1769   ['three, 'three],
1770   ['four, 'four],
1771   ['five, 'five],
1772   ['six, 'six],
1773   ['seven, 'seven],
1774   ['more_than_seven, 'more_than_seven],
1775   ['more_than_seven, 'more_than_seven]]];
1777 (kill (foo, bar, l1, l2, inputs, to_else_if, with_both_elseifs), 0);
1780 /* Bogus translations of conditionals with tests that translated to T
1781  * and consequents that translated to NIL.
1782  */
1784 block ([translate : false],
1785   foo () :=
1786     [if true then false else 1,
1787      if true then false elseif true then 1 else 2,
1788      if false then true elseif true then false else 1],
1790   /* l1: foo is interpreted */
1791   l1 : foo (),
1793   translate_or_lose (foo),
1795   /* l2: foo is translated
1796    *
1797    * foo used to return [1, 1, 1]
1798    */
1799   l2 : foo (),
1801   [is (l2 = l1),
1802    l2]);
1803 [true,
1804  [false, false, false]];
1806 (kill (foo, l1, l2), 0);
1809 /* Bug #3704: Translator gives internal error
1811  * The hyper_to_summand function is from the bug report.
1812  */
1814 (hyper_to_summand(e,k) := subst(hypergeometric = lambda([P,Q,x], 
1815     P : xreduce("*", map(lambda([zz], pochhammer(zz,k)),P)),
1816     Q : xreduce("*", map(lambda([zz], pochhammer(zz,k)),Q)),
1817     P*x^k/(k! * Q)),e),
1818  l1 : hyper_to_summand (hypergeometric ([1/2], [2/5], x), 2),
1819  translate_or_lose (hyper_to_summand),
1820  l2 : hyper_to_summand (hypergeometric ([1/2], [2/5], x), 2),
1821  [is (l1 = l2), l2]);
1822 [true, 75 * x^2 / 112];
1824 (foo () := lambda ([], x!),
1825  translate_or_lose (foo),
1826  block ([x : 5], foo () ()));
1827 120;
1829 (kill (hyper_to_summand, foo, l1, l2), 0);
1832 /* go tags can be integers
1834  * This has been allowed, but it used to give a warning and an extra
1835  * trivial run through the translator to translate the integer go tags.
1836  * Now we allow integers directly without giving a warning.
1838  * We don't actually bother to check for warnings in the test below.
1839  * We're really just verifying that using an integer go tag works.
1840  */
1842 block ([translate : false],
1843   foo () := block ([i : 0], tag, i : i + 1, if i < 5 then go (tag), i),
1844   bar () := block ([i : 0], 123, i : i + 1, if i < 5 then go (123), i),
1845   l1 : [foo (), bar ()],
1846   translate_or_lose (foo, bar),
1847   l2 : [foo (), bar ()],
1848   [is (l1 = l2), l2]);
1849 [true, [5, 5]];
1851 (kill (foo, bar, l1, l2), 0);
1854 /* A bug in MARRAYREF caused things like translated array references
1855  * to yield MQAPPLY expressions with an incorrect header.
1856  */
1858 block ([translate : false],
1859   foo () := 'baz () [1],
1860   bar () := 'baz () [1, 2, 3],
1861   l1 : [foo (), bar ()],
1862   translate_or_lose (foo, bar),
1863   l2 : [foo (), bar ()],
1864   [is (l1 = l2), l2]);
1865 [true, ['baz () [1], 'baz () [1, 2, 3]]];
1867 (kill (foo, bar, l1, l2), 0);
1870 /* A bug in MARRAYREF caused bogus indexing into hash tables and fast
1871  * arrays.  This affected things like translated array references.
1872  */
1874 block ([translate : false,
1875         use_fast_arrays : true],
1877   foo () := block ([a],
1878               a[false] : 'wtf,
1879               a[1] : 2,
1880               a[1]),
1882   /* This would correctly yield 2 */
1883   l1 : foo (),
1885   translate_or_lose (foo),
1887   /* This used to incorrectly yield wtf */
1888   l2 : foo (),
1890   [is (l1 = l2), l2]);
1891 [true, 2];
1893 (kill (foo, l1, l2), 0);
1896 /* A bug in MARRAYREF caused things like translated array references
1897  * to yield expressions with an incorrect header.
1898  */
1900 block ([translate : false],
1901   foo () := block ([a],
1902               local (a),
1903               array (a, complete, 5),
1904               a[3]),
1906   /* This would correctly yield a[3] */
1907   l1 : foo(),
1909   translate_or_lose (foo),
1911   /* This would incorrectly yield a(3) */
1912   l2 : foo(),
1914   [is (l1 = l2), l2]);
1915 [true, 'a[3]];
1917 (kill (foo, l1, l2), 0);
1920 /* When translate_fast_arrays:true, a lisp error would occur at runtime
1921  * during an attempted MQAPPLY array assignment
1922  */
1924 block ([translate : false],
1925   foo () := block ([a],
1926               local (a, b),
1927               a : make_array ('fixnum, 5),
1928               b () := a,
1929               b () [3] : 17,
1930               b () [3]),
1932   /* This would correctly yield 17 */
1933   l1 : foo(),
1935   block ([translate_fast_arrays : false],
1936     translate_or_lose (foo)),
1938   /* This would correctly yield 17 */
1939   l2 : foo(),
1941   block ([translate_fast_arrays : true],
1942     translate_or_lose (foo)),
1944   /* This would cause a lisp error */
1945   l3 : foo(),
1947   [is (l1 = l2), is (l2 = l3), l3]);
1948 [true, true, 17];
1950 (kill (foo, l1, l2, l3), 0);
1953 /* The string "**" no longer translates to the string "^".
1954  * This test compares the interpreted and translated results.
1955  */
1957 block ([translate : false],
1958   foo () := ["^", "^" (2, 3), apply ("^", [2, 3]),
1959              "**", "**" (2, 3), apply ("**", [2, 3])],
1960   l1 : foo (),
1961   translate_or_lose (foo),
1962   l2 : foo (),
1963   [l2, is (l1 = l2)]);
1964 [["^", 8, 8, "**", 8, 8], true];
1966 (kill (foo, l1, l2), 0);
1969 /* Attempting to translate some atoms like lisp arrays would
1970  * cause lisp errors during translation.
1971  */
1973 (a : make_array (fixnum, 1),
1974  a[0] : 13,
1975  define (foo (), a),
1976  translate_or_lose (foo),
1977  listarray (foo ()));
1978 [13];
1980 (kill (foo, a), 0);
1983 /* Simple tests for catch and throw */
1985 block ([translate : false, l1, l2],
1986   local (foo, bar, baz),
1988   foo (p) := if p then throw (13) else 2,
1989   bar () := catch (1, foo (false), 3),
1990   baz () := catch (1, foo (true), 3),
1992   l1 : [bar (), baz ()],
1994   translate_or_lose (foo, bar, baz),
1996   l2 : [bar (), baz ()],
1998   [l2, is (l1 = l2)]);
1999 [[3, 13], true];
2001 block ([translate : false, l1, l2],
2002   local (foo, bar),
2004   foo (p) := throw (if p then 1/2 else 'other),
2005   bar (p) := 1 + catch (foo (p), 2),
2007   l1 : [bar (true), bar (false)],
2009   translate_or_lose (foo, bar),
2011   l2 : [bar (true), bar (false)],
2013   [l2, is (l1 = l2)]);
2014 [[3/2, 1 + 'other], true];
2016 (kill (foo, bar), 0);
2019 /* Translating a define_variable form with translate (but not
2020  * translate_file or compfile) used to invoke undefined behavior.
2021  * This would cause a lisp error during translation under some
2022  * (but not all) lisp implementations.
2023  */
2025 block ([translate : false],
2026   local (foo),
2027   foo () := (define_variable (x, 1, fixnum), x),
2028   translate_or_lose (foo),
2029   foo ());
2032 (kill (foo, x), 0);
2035 /* If local was used on a matchdeclared pattern variable, and this
2036  * was all translated with something besides translate_file (e.g.,
2037  * translate, compfile, etc.), then the MATCHDECLARE property would
2038  * not be on the pattern variable.
2039  */
2041 block ([translate : false, l1, l2],
2042   local (foo),
2044   foo () := (local (x), matchdeclare (x, true), let (a * x, x), letsimp (a * q)),
2046   /* This would yield q */
2047   l1 : foo (),
2049   translate_or_lose (foo),
2051   /* This used to yield a*q */
2052   l2 : foo (),
2054   [l2, is (l1 = l2)]);
2055 [q, true];
2057 (kill (foo), 0);
2060 /* Rest args are now allowed in lambda expressions in MQAPPLY
2061  * lambda forms
2062  */
2064 block ([translate : false, l1, l2],
2065   local (foo, bar, baz),
2067   /* foo used to fail to translate due to the rest arg */
2068   foo () :=
2069     block ([x : 1, z : 3],
2070       lambda ([[x]], x) (x, x + 1, z)),
2071   bar () :=
2072     block ([x : 2, z : 4],
2073       apply (lambda ([[x]], x), [x, x + 1, z])),
2074   baz () :=
2075     block ([x : 3, z : 5],
2076       block ([f : lambda ([[x]], x)],
2077         f (x, x + 1, z))),
2079   l1 : [foo (), bar (), baz ()],
2081   translate_or_lose (foo, bar, baz),
2083   l2 : [foo (), bar (), baz ()],
2085   [l1, is (l1 = l2)]);
2086 [[[1, 2, 3],[2, 3, 4],[3, 4, 5]], true];
2088 /* Validation has been improved for lambda expressions in MQAPPLY
2089  * lambda forms
2090  */
2092 block ([translate : false],
2093   local (foo, bar),
2095   /* These should both fail to translate */
2096   foo () := lambda ([]) (),
2097   bar () := lambda ([x, x], x) (1, 2),
2099   translate (foo, bar));
2102 /* The translation of array functions was broken for decades */
2104 block ([translate : false, l1, l2],
2105   local (foo, bar),
2107   foo[x] := x,
2108   bar[n] := if n = 1 then 1 else n * bar[n - 1],
2110   l1 : [foo[0], foo[5], bar[5], bar[10]],
2112   translate_or_lose (foo, bar),
2114   l2 : [foo[0], foo[5], bar[5], bar[10]],
2116   [l1, is (l1 = l2)]);
2117 [[0, 5, 120, 3628800], true];
2119 (kill (foo, bar), 0);
2122 /* The translation of upward funargs (including those created by
2123  * subscripted functions) easily lead to lisp errors.
2124  */
2126 /* Tests involving returned lambdas without free vars that were
2127  * bound during definition
2128  */
2129 block ([l1, l2,
2130         translate : false,
2131         listarith : true],
2132   local (foo, bar, test),
2134   foo () := lambda ([x], 2 * x + q),
2135   bar () := lambda ([x, [y]], x * y + q),
2137   test () :=
2138     block ([f : foo (),
2139             b : bar ()],
2140       [f (3), f (5), b (2, 3, 4), b (5, 6, 7)]),
2142   l1 : test (),
2144   translate_or_lose (foo, bar),
2146   l2 : test (),
2148   [l2, is (l1 = l2)]);
2149 [['q + 6, 'q + 10, ['q + 6, 'q + 8], ['q + 30, 'q + 35]],
2150  true];
2152 (kill (foo, bar), 0);
2155 /* Tests involving returned lambdas with free vars that were
2156  * bound during definition.  These do not cause the capture of
2157  * values.
2158  */
2159 block ([l1, l2,
2160         x : 'ux,
2161         translate : false,
2162         listarith : true],
2163   local (foo, bar, baz, test),
2165   foo (x) := lambda ([y], x + y + q),
2166   bar (x) := lambda ([y, [z]], q + x + y * z),
2167   baz (v) := lambda ([], v),
2169   test () :=
2170     block ([f : foo (3),
2171             b : bar (4),
2172             c : baz (5)],
2173       [f (5), b (2, 3, 4), c ()]),
2175   l1 : test (),
2177   translate_or_lose (foo, bar, baz),
2179   l2 : test (),
2181   [l2, is (l1 = l2)]);
2182 [['q + 'ux + 5,
2183   ['q + 'ux + 6, 'q + 'ux + 8],
2184   'v],
2185  true];
2187 (kill (foo, bar, baz), 0);
2190 /* Tests involving subscripted functions.  These do cause the capture
2191  * of values.
2192  */
2193 block ([l1, l2,
2194         x : 'ux, y : 'uy,
2195         translate : false],
2196   local (foo, bar, baz, def, test),
2198   def () := (
2199     foo[x, y](a, b) := [x, y, a, b, q],
2200     bar[x, y](a, [b]) := [x, y, a, b, q],
2201     baz[v]() := v),
2203   test () :=
2204     block ([f : foo[1, 2],
2205             b : bar[3, 4],
2206             c : baz[5]],
2207       [f (6, 7), b (8, 9, 10), c ()]),
2209   def (),
2211   l1 : test (),
2213   /* just kill and redefine */
2215   kill (foo, bar, baz),
2217   def (),
2219   translate_or_lose (foo, bar, baz),
2221   l2 : test (),
2223   [l2, is (l1 = l2)]);
2224 [[[1, 2, 6, 7, 'q],
2225   [3, 4, 8, [9, 10], 'q],
2226   5],
2227  true];
2229 (kill (foo, bar, baz), 0);
2232 /* More tests involving multiple nested lambdas */
2233 block ([l1, l2,
2234         x : 'ux, y : 'uy, z : 'uz,
2235         translate : false],
2236   local (foo, bar, baz, quux, def, test),
2238   def () := (
2239     /* nothing should be captured */
2240     foo (x) := lambda ([y], lambda ([z], [x, y, z])),
2241     /* x should be captured and used */
2242     bar[x](y) := lambda ([z], [x, y, z]),
2243     /* x should be captured and used */
2244     baz[x](y) := lambda ([z], lambda ([], [x, y, z])),
2245     /* nothing should be captured since x is bound by the inner lambda */
2246     quux[x](y) := lambda ([x], [x, y])),
2248   test () :=
2249     block ([a : foo (1),
2250             b : bar[2],
2251             c : baz[3],
2252             d : quux[4]],
2253       [a (10) (11), b (12) (13), c (14) (15) (), d (16) (17)]),
2255   def (),
2257   l1 : test (),
2259   /* just kill and redefine */
2261   kill (foo, bar, baz, quux),
2263   def (),
2265   translate_or_lose (foo, bar, baz, quux),
2267   l2 : test (),
2269   [l2, is (l1 = l2)]);
2270 [[['ux, 'uy, 11],
2271   [2, 'uy, 13],
2272   [3, 'uy, 'uz],
2273   [17, 'uy]],
2274  true];
2276 (kill (foo, bar, baz, quux), 0);
2279 /* The translator was not correctly determining the mode of expressions
2280  * when a boolean mode was involved.
2282  * It was easy to get lisp errors.
2283  */
2284 block ([translate : false, l1, l2],
2285   local (test),
2287   foo () :=
2288     [  1 + if true then 0,
2289        1 + if true then 0.0,
2290      1.0 + if true then 0,
2291      1.0 + if true then 0.0,
2293        1 + if false then 0,
2294        1 + if false then 0.0,
2295      1.0 + if false then 0,
2296      1.0 + if false then 0.0],
2298   bar (x) :=
2299     [  1 + if x then 0,
2300        1 + if x then 0.0,
2301      1.0 + if x then 0,
2302      1.0 + if x then 0.0],
2304   test () :=
2305     block ([res : []],
2306       for prederror in [true, false] do
2307         push (foo (), res),
2308         for x in [true, false] do
2309           push (bar (x), res),
2310       res),
2312   l1 : test (),
2314   translate_or_lose (foo, bar),
2316   l2 : test (),
2318   is (l1 = l2));
2319 true;
2321 (kill (foo, bar), 0);
2325  * Bug #4008: translator and prederror
2326  */
2328 (kill (pred, foo, bar, x, r), 0);
2331 block ([translate : false, l1, l2],
2332   local (test),
2334   foo (n, q, x) :=
2335     [if true then q + r,
2336      if false then q + r,
2338      if x then q,
2339      if not x then q,
2340      if not not x then q,
2341      if not not not x then q,
2343      n + if x then q + r,
2344      n + if not x then q + r,
2345      n + if not not x then q + r,
2346      n + if not not not x then q + r],
2348   test () :=
2349     block ([res : []],
2350       for prederror in [true, false] do
2351         for n in [1, 1.0, %i, 1.0 * %i] do
2352           for q in [1, 1.0, %i, 1.0 * %i, 'z] do
2353             for x in [true, false] do
2354               push (foo (n, q, x), res),
2355       res),
2357   l1 : test (),
2359   translate_or_lose (foo),
2361   l2 : test (),
2363   is (l1 = l2));
2364 true;
2366 (kill (foo), 0);
2369 block ([translate : false, l1, l2],
2370   local (test),
2372   foo (x, y) :=
2373     block ([q : 'z],
2374       [if "and" () then q else r,
2375        if "and" (x) then q else r,
2376        if "and" (y) then q else r,
2377        if x and y then q else r,
2378        if not x and y then q else r,
2379        if x and not y then q else r,
2380        if not x and not y then q else r,
2381        if not (x and y) then q else r,
2382        if not (not x and y) then q else r,
2383        if not (x and not y) then q else r,
2384        if not (not x and not y) then q else r,
2386        if "or" () then q else r,
2387        if "or" (x) then q else r,
2388        if "or" (y) then q else r,
2389        if x or y then q else r,
2390        if not x or y then q else r,
2391        if x or not y then q else r,
2392        if not x or not y then q else r,
2393        if not (x or y) then q else r,
2394        if not (not x or y) then q else r,
2395        if not (x or not y) then q else r,
2396        if not (not x or not y) then q else r]),
2398   test () :=
2399     block ([res : []],
2400       for prederror in [true, false] do
2401         for x in [true, false] do
2402           for y in [true, false] do
2403             push (foo (x, y), res),
2404       res),
2406   l1 : test (),
2408   translate_or_lose (foo),
2410   l2 : test (),
2412   is (l1 = l2));
2413 true;
2415 (kill (foo), 0);
2418 block ([translate : false, l1, l2],
2419   local (test, make_fun),
2421   make_fun (name, pr) ::=
2422     buildq ([name, pr],
2423       name (x, y) :=
2424         block ([q : 'z],
2425           [pr ("and" ()),
2426            pr ("and" (x)),
2427            pr ("and" (y)),
2428            pr (x and y),
2429            pr (not x and y),
2430            pr (x and not y),
2431            pr (not x and not y),
2432            pr (not (x and y)),
2433            pr (not (not x and y)),
2434            pr (not (x and not y)),
2435            pr (not (not x and not y)),
2437            pr ("or" ()),
2438            pr ("or" (x)),
2439            pr ("or" (y)),
2440            pr (x or y),
2441            pr (not x or y),
2442            pr (x or not y),
2443            pr (not x or not y),
2444            pr (not (x or y)),
2445            pr (not (not x or y)),
2446            pr (not (x or not y)),
2447            pr (not (not x or not y))])),
2449   make_fun (foo, is),
2450   make_fun (bar, maybe),
2452   test () :=
2453     block ([res : []],
2454       for prederror in [true, false] do
2455         for x in [true, false] do
2456           for y in [true, false] do (
2457             push (foo (x, y), res),
2458             push (bar (x, y), res)),
2459       res),
2461   l1 : test (),
2463   translate_or_lose (foo, bar),
2465   l2 : test (),
2467   is (l1 = l2));
2468 true;
2470 (kill (foo, bar), 0);
2473 block ([translate : false, l1, l2],
2474   local (test),
2476   pred (a, b) := equal (a, b),
2478   foo (x, y) :=
2479     block ([q : 'z],
2480       [if x < y then q else r,
2481        if not (x < y) then q else r,
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,
2489        if x = y then q else r,
2490        if x # y then q else r,
2491        if not (x = y) then q else r,
2492        if not (x # y) then q else r,
2493        if not not (x = y) then q else r,
2494        if not not (x # y) then q else r,
2495        if not not not (x = y) then q else r,
2496        if not not not (x # y) then q else r,
2498        if equal (x, y) then q else r,
2499        if notequal (x, y) then q else r,
2500        if not equal (x, y) then q else r,
2501        if not not equal (x, y) then q else r,
2502        if not notequal (x, y) then q else r,
2503        if not not not equal (x, y) then q else r,
2504        if not not notequal (x, y) then q else r,
2506        if pred (x, y) then q else r,
2507        if not pred (x, y) then q else r,
2508        if not not pred (x, y) then q else r,
2509        if not not not pred (x, y) then q else r]),
2511   test () :=
2512     block ([res : []],
2513       for prederror in [true, false] do
2514         for x in [1, 2] do
2515           for y in [1, 2] do
2516             push (foo (x, y), res),
2517       res),
2519   l1 : test (),
2521   translate_or_lose (pred, foo),
2523   l2 : test (),
2525   is (l1 = l2));
2526 true;
2528 (kill (pred, foo), 0);
2531 block ([translate : false, l1, l2],
2532   local (test, make_fun),
2534   pred (a, b) := equal (a, b),
2536   make_fun (name, pr) ::=
2537     buildq ([name, pr],
2538       name (x, y) :=
2539         block ([q : 'z],
2540           [pr (x = y),
2541            pr (x # y),
2542            pr (not (x = y)),
2543            pr (not (x # y)),
2544            pr (not not (x = y)),
2545            pr (not not (x # y)),
2546            pr (not not not (x = y)),
2547            pr (not not not (x # y)),
2549            pr (equal (x, y)),
2550            pr (not equal (x, y)),
2551            pr (notequal (x, y)),
2552            pr (not not equal (x, y)),
2553            pr (not notequal (x, y)),
2554            pr (not not not equal (x, y)),
2555            pr (not not notequal (x, y)),
2557            pr (pred (x, y)),
2558            pr (not pred (x, y)),
2559            pr (not not pred (x, y)),
2560            pr (not not not pred (x, y))])),
2562   make_fun (foo, is),
2563   make_fun (bar, maybe),
2565   test () :=
2566     block ([res : []],
2567       for prederror in [true, false] do
2568         for x in [1, 2] do
2569           for y in [1, 2] do (
2570             push (foo (x, y), res),
2571             push (bar (x, y), res)),
2572       res),
2574   l1 : test (),
2576   translate_or_lose (pred, foo, bar),
2578   l2 : test (),
2580   is (l1 = l2));
2581 true;
2583 (kill (pred, foo, bar), 0);
2586 block ([translate : false, l1, l2],
2587   local (test),
2589   foo (x, q) :=
2590     [if (1, 2, q, x) then q else r,
2591      if not (1, 2, q, x) then q else r,
2592      if (1, 2, q, not x) then q else r],
2594   test () :=
2595     block ([res : []],
2596       for prederror in [true, false] do
2597         for x in [true, false] do
2598           push (foo (x, 17), res),
2599       res),
2601   l1 : test (),
2603   translate_or_lose (foo),
2605   l2 : test (),
2607   is (l1 = l2));
2608 true;
2610 (kill (foo), 0);
2613 block ([translate : false, l1, l2],
2614   local (test, make_fun),
2616   make_fun (name, pr) ::=
2617     buildq ([name, pr],
2618       name (x, y) :=
2619         [pr (x),
2620          pr (not x),
2621          pr (not not x),
2622          pr (not not not x),
2624          pr (y),
2625          pr (not y),
2626          pr (not not y),
2627          pr (not not not y),
2629          pr (x and y),
2630          pr (x or y),
2631          pr (not (x and y)),
2632          pr (not (x or y)),
2633          pr (not not (x and y)),
2634          pr (not not (x or y)),
2635          pr (not not not (x and y)),
2636          pr (not not not (x or y)),
2638          pr (x and not y),
2639          pr (x or not y),
2640          pr (x and not not y),
2641          pr (x or not not y),
2642          pr (not (x and not y)),
2643          pr (not (x or not y)),
2644          pr (not (x and not not y)),
2645          pr (not (x or not not y)),
2647          pr (not x and y),
2648          pr (not x or y),
2649          pr (not not x and y),
2650          pr (not not x or y),
2651          pr (not (not x and y)),
2652          pr (not (not x or y)),
2653          pr (not (not not x and y)),
2654          pr (not (not not x or y)),
2656          pr (not x and not y),
2657          pr (not x or not y),
2658          pr (not (not x and not y)),
2659          pr (not (not x or not y)),
2661          pr (x > 1),
2662          pr (not x > 1),
2663          pr (x > 1 and y),
2664          pr (x > 1 or y),
2665          pr (x > 1 and not y),
2666          pr (x > 1 or not y),
2667          pr (not x > 1 and y),
2668          pr (not x > 1 or y),
2669          pr (not x > 1 and not y),
2670          pr (not x > 1 or not y),
2672          pr (y <= 1),
2673          pr (not y <= 1),
2674          pr (x and y <= 1),
2675          pr (x or y <= 1),
2676          pr (x and not y <= 1),
2677          pr (x or not y <= 1),
2678          pr (not x and y <= 1),
2679          pr (not x or y <= 1),
2680          pr (not x and not y <= 1),
2681          pr (not x or not y <= 1)]),
2683   make_fun (foo, is),
2684   make_fun (bar, maybe),
2686   test () :=
2687     block ([prederror : false,
2688             l : [true, false, 1, 2.0, 'q, 'q ()],
2689             res : []],
2690       for x in l do
2691         for y in l do (
2692           push (foo (x, y), res),
2693           push (bar (x, y), res)),
2694       res),
2696   l1 : test (),
2698   translate_or_lose (foo, bar),
2700   l2 : test (),
2702   is (l1 = l2));
2703 true;
2705 (kill (foo, bar), 0);
2708 block ([translate : false, l1, l2],
2709   local (test, make_fun),
2711   make_fun (name, pr) ::=
2712     buildq ([name, pr],
2713       name (x) :=
2714         [pr (x <  1),
2715          pr (x <= 1),
2716          pr (x >  1),
2717          pr (x >= 1),
2719          pr (not (x <  1)),
2720          pr (not (x <= 1)),
2721          pr (not (x >  1)),
2722          pr (not (x >= 1)),
2724          pr (not not (x <  1)),
2725          pr (not not (x <= 1)),
2726          pr (not not (x >  1)),
2727          pr (not not (x >= 1)),
2729          pr (x = 1),
2730          pr (x # 1),
2731          pr (not (x = 1)),
2732          pr (not (x # 1)),
2733          pr (not not (x = 1)),
2734          pr (not not (x # 1)),
2736          pr (equal (x, 1)),
2737          pr (notequal (x, 1)),
2738          pr (not equal (x, 1)),
2739          pr (not notequal (x, 1)),
2740          pr (not not equal (x, 1)),
2741          pr (not not notequal (x, 1))]),
2743   make_fun (foo, is),
2744   make_fun (bar, maybe),
2746   test () :=
2747     block ([res : []],
2748       block ([prederror : true],
2749         push (errcatch (foo ('z)), res)),
2750       block ([prederror : false,
2751               l : [0, 0.0, 0.0b0,
2752                    1, 1.0, 1.0b0,
2753                    2, 2.0, 2.0b0,
2754                    %i, 1.0 * %i, 1.0b0 * %i,
2755                    2 * %i, 2.0 * %i, 2.0b0 * %i,
2756                    true, false,
2757                    'z, 'z ()]],
2758         for x in l do (
2759           push (foo (x), res),
2760           push (bar (x), res))),
2761       res),
2763   l1 : test (),
2765   translate_or_lose (foo, bar),
2767   l2 : test (),
2769   is (l1 = l2));
2770 true;
2772 (kill (foo, bar), 0);
2775 block ([translate : false, l1, l2],
2776   local (test),
2778   foo (x, q, prederror) :=
2779     block ([r],
2780       [if x then 0,
2781        if not x then 0,
2782        if not not x then 0,
2783        if not not not x then 0,
2784        if x then q + r,
2785        if not x then q + r,
2786        if not not x then q + r,
2787        if not not not x then q + r,
2788        if x then 1 else 2,
2789        if not x then 1 else 2,
2790        if not not x then 1 else 2,
2791        if not not not x then 1 else 2,
2792        if x then x else q + r,
2793        if not x then x else q + r,
2794        if not not x then x else q + r,
2795        if not not not x then x else q + r,
2796        if x = 1 then x else q + r,
2797        if x # 1 then x else q + r,
2798        if not x = 1 then x else q + r,
2799        if not x # 1 then x else q + r,
2800        if not not x = 1 then x else q + r,
2801        if not not x # 1 then x else q + r,
2802        if not not not x = 1 then x else q + r,
2803        if not not not x # 1 then x else q + r]),
2805   test () :=
2806     block ([l : [true, false, 1, 2.0, 3.0b0, 'z, 'z ()],
2807             res : []],
2808       push (errcatch (foo (1, 2, true)), res),
2809       for x in l do
2810         for q in l do
2811           push (foo (x, q, false), res),
2812       res),
2814   l1 : test (),
2816   translate_or_lose (foo),
2818   l2 : test (),
2820   is (l1 = l2));
2821 true;
2823 (kill (foo), 0);
2826 block ([translate : false, l1, l2],
2827   local (rewritehack, eqhack, test),
2829   /* Take a relational expr and potentially rewrite it in some
2830    * equivalent way, e.g.  x<1  =>  1-x>0
2831    */
2832   rewritehack (r) :=
2833     eval_string_lisp ("(apply #'mevalp2 $r (mop $r) (margs $r))")[1],
2835   /* Translated code can produce relational exprs that are in a
2836    * different, but equivalent, form compared to the exprs produce
2837    * by interpreted code.
2838    *
2839    * Compare two conditionals by requiring that everything matches
2840    * exactly, except possibly the first (only) test.  The tests
2841    * should match exactly after applying rewritehack to them.
2842    */
2843   eqhack (interp, transl) :=
2844     if atom (interp) or atom (transl) or op (interp) # "if" or op (transl) # "if" then
2845       is (interp = transl)
2846     else
2847       is (rest (interp) = rest (transl)
2848           and
2849           rewritehack (first (interp)) = rewritehack (first (transl))),
2851   foo (x) :=
2852     block ([r],
2853       [if x <  1 then x else r,
2854        if x <= 1 then x else r,
2855        if x >  1 then x else r,
2856        if x >= 1 then x else r,
2858        if not (x <  1) then x else r,
2859        if not (x <= 1) then x else r,
2860        if not (x >  1) then x else r,
2861        if not (x >= 1) then x else r,
2863        if not not (x <  1) then x else r,
2864        if not 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,
2868        if x = 1 then x else r,
2869        if x # 1 then x else r,
2870        if not (x = 1) then x else r,
2871        if not (x # 1) then x else r,
2872        if not not (x = 1) then x else r,
2873        if not not (x # 1) then x else r,
2875        if equal (x, 1) then x else r,
2876        if notequal (x, 1) then x else r,
2877        if not equal (x, 1) then x else r,
2878        if not notequal (x, 1) then x else r,
2879        if not not equal (x, 1) then x else r,
2880        if not not notequal (x, 1) then x else r]),
2882   test () :=
2883     block ([res : []],
2884       block ([prederror : true],
2885         push (errcatch (foo ('z)), res)),
2886       block ([prederror : false,
2887               l : [0, 0.0, 0.0b0,
2888                    1, 1.0, 1.0b0,
2889                    2, 2.0, 2.0b0,
2890                        %i, 1.0 * %i, 1.0b0 * %i,
2891                    2 * %i, 2.0 * %i, 2.0b0 * %i,
2892                    true, false,
2893                    'z, 'z ()]],
2894         for x in l do
2895           res : append (foo (x), res)),
2896       res),
2898   l1 : test (),
2900   translate_or_lose (foo),
2902   l2 : test (),
2904   every (eqhack, l1, l2));
2905 true;
2907 (kill (foo), 0);
2910 block ([translate : false, l1, l2],
2911   local (test),
2913   foo (x, y, z) :=
2914     block ([r],
2915       [if x >  0 and y >  0 and z >  0 then x + y = z else r,
2916        if x >  0 or  y >  0 or  z >  0 then x + y = z else r,
2917        if x >= 1 and y >= 1 and z >= 1 then x + y = z else r,
2918        if x >= 1 or  y >= 1 or  z >= 1 then x + y = z else r,
2919        if x <= 2 and y <= 2 and z <= 2 then x + y = z else r,
2920        if x <= 2 or  y <= 2 or  z <= 2 then x + y = z else r,
2921        if x <  3 and y <  3 and z <  3 then x + y = z else r,
2922        if x <  3 or  y <  3 or  z <  3 then x + y = z else r]),
2924   test () :=
2925     block ([l : [1, 2.0, 3.0b0, %i],
2926             res : []],
2927       for x in l do
2928         for y in l do
2929           for z in l do
2930             push (foo (x, y, z), res),
2931       res),
2933   l1 : test (),
2935   translate_or_lose (foo),
2937   l2 : test (),
2939   is (l1 = l2));
2940 true;
2942 (kill (foo), 0);
2945 block ([translate : false, l1, l2],
2946   local (test),
2948   foo (p, x, y, z) :=
2949     (modedeclare (p, boolean, x, fixnum, y, flonum, z, number),
2950       block ([r],
2951         [if p and x >  0 and y >  0 and z >  0 then x + y - z else r,
2952          if p or  x >  0 or  y >  0 or  z >  0 then x + y - z else r,
2953          if p and x >= 1 and y >= 1 and z >= 1 then x + y - z else r,
2954          if p or  x >= 1 or  y >= 1 or  z >= 1 then x + y - z else r,
2955          if p and x <= 2 and y <= 2 and z <= 2 then x + y - z else r,
2956          if p or  x <= 2 or  y <= 2 or  z <= 2 then x + y - z else r,
2957          if p and x <  3 and y <  3 and z <  3 then x + y - z else r,
2958          if p or  x <  3 or  y <  3 or  z <  3 then x + y - z else r,
2960          if p and x >  y and y >  z and z >  3 then x + y + z else r,
2961          if p or  x >  y or  y >  z or  z >  3 then x + y + z else r,
2962          if p and x >= y and y >= z and z >= 2 then x + y + z else r,
2963          if p or  x >= y or  y >= z or  z >= 2 then x + y + z else r,
2964          if p and x <= y and y <= z and z <= 1 then x + y + z else r,
2965          if p or  x <= y or  y <= z or  z <= 1 then x + y + z else r,
2966          if p and x <  y and y <  z and z <  0 then x + y + z else r,
2967          if p or  x <  y or  y <  z or  z <  0 then x + y + z else r])),
2969   test () :=
2970     block ([bool : [true, false],
2971             fixl : [0, 1, 2, 3, 4],
2972             flol : [0.0, 1.0, 2.0, 3.0, 4.0],
2973             numl : [0, 1.0, 2, 3.0, 4],
2974             res : []],
2975       for p in bool do
2976         for x in fixl do
2977           for y in flol do
2978             for z in numl do
2979               push (foo (p, x, y, z), res),
2980       res),
2982   l1 : test (),
2984   translate_or_lose (foo),
2986   l2 : test (),
2988   is (l1 = l2));
2989 true;
2991 (kill (foo, p, x, y, z), 0);
2994 block ([translate : false, l1, l2],
2995   local (test),
2997   foo (p, x, y, z) :=
2998     block ([r],
2999       [if p and x and y and z then x + y = z else r,
3000        if p or  x or  y or  z then x + y = z else r,
3002        if p and equal (x, 1) and equal (y, 1) and equal (z, 1) then x + y = z else r,
3003        if p or  equal (x, 1) or  equal (y, 1) or  equal (z, 1) then x + y = z else r,
3005        if not p and not equal (x, 1) and not equal (y, 1) and not equal (z, 1) then x + y = z else r,
3006        if not p or  not equal (x, 1) or  not equal (y, 1) or  not equal (z, 1) then x + y = z else r,
3008        if p and notequal (x, 1) and notequal (y, 1) and notequal (z, 1) then x + y = z else r,
3009        if p or  notequal (x, 1) or  notequal (y, 1) or  notequal (z, 1) then x + y = z else r,
3011        if not p and not notequal (x, 1) and not notequal (y, 1) and not notequal (z, 1) then x + y = z else r,
3012        if not p or  not notequal (x, 1) or  not notequal (y, 1) or  not notequal (z, 1) then x + y = z else r]),
3014   test () :=
3015     block ([prederror : false,
3016             l : [true, false, 1, 2.0, 3.0b0, %i, 'z, 'z ()],
3017             res : []],
3018       for p in [true, false] do
3019         for x in l do
3020           for y in l do
3021             for z in l do
3022               push (foo (p, x, y, z), res),
3023       res),
3025   l1 : test (),
3027   translate_or_lose (foo),
3029   l2 : test (),
3031   is (l1 = l2));
3032 true;
3034 (kill (foo), 0);
3037 block ([translate : false, l1, l2],
3038   local (test),
3040   pred (a, b) := equal (a, b),
3042   foo (x, q) :=
3043     block ([r, var1, var2, v1 : 'var1, v2 : 'var2],
3044       [if pred (x, 1) then x,
3045        if not pred (x, 1) then x,
3046        if pred (x, 1) or pred (x, 2) then x,
3047        if pred (x, 1) then x else q + r,
3048        if not pred (x, 1) then x else q + r,
3049        if pred (x, 1) or pred (x, 2) then x else q + r,
3050        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,
3051        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,
3052        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,
3053        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,
3054        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,
3055        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]),
3057   test () :=
3058     block ([res : []],
3059       block ([prederror : false],
3060         push (errcatch (foo (true, false)), res)),
3061       block ([prederror : false,
3062               l : [true, false, 1, 2.0, 3.0b0, %i, 'z, 'z ()]],
3063         for x in l do
3064           for q in l do
3065             push (foo (x, q), res)),
3066       res),
3068   l1 : test (),
3070   translate_or_lose (pred, foo),
3072   l2 : test (),
3074   is (l1 = l2));
3075 true;
3077 (kill (pred, foo), 0);
3080 block ([translate : false, l1, l2],
3081   local (test),
3083   /* I really want push(x,a) below in foo, bar and baz,
3084    * but the translation of the push special form just
3085    * punts to MEVAL.  I want the loop bodies translated
3086    * better than that, especially in baz, so just do
3087    * a:cons(x,a) everywhere here.
3088    */
3090   foo () :=
3091     [block ([a : []],
3092        for x : 1 thru 5 do a : cons (x, a),
3093        a),
3094      block ([a : []],
3095        for x : 1 thru 5 while x < 3 do a : cons (x, a),
3096        a),
3097      block ([a : []],
3098        for x : 1 thru 5 while x > 3 do a : cons (x, a),
3099        a),
3100      block ([a : []],
3101        for x : 1 thru 5 while x < 10 do a : cons (x, a),
3102        a),
3103      block ([a : []],
3104        for x : 1 thru 5 while x > 10 do a : cons (x, a),
3105        a),
3106      block ([a : []],
3107        for x : 1 thru 5 unless x < 3 do a : cons (x, a),
3108        a),
3109      block ([a : []],
3110        for x : 1 thru 5 unless x > 3 do a : cons (x, a),
3111        a)],
3113   bar (p) :=
3114     [block ([a : []],
3115        for x : 1 thru 5 while p do a : cons (x, a),
3116        a),
3117      block ([a : []],
3118        for x : 1 thru 5 while x < 3 and p do a : cons (x, a),
3119        a),
3120      block ([a : []],
3121        for x : 1 thru 5 while x < 3 or p do a : cons (x, a),
3122        a),
3123      block ([a : []],
3124        for x : 1 thru 5 while x < 10 or 'z do a : cons (x, a),
3125        a)],
3127   baz () :=
3128     [block ([a : []],
3129        for x : 1 thru 5 do a : cons (if x then x else false, a),
3130        a),
3131      block ([a : []],
3132        for x : 1 thru 5 while x < 3 do a : cons (if x then x else false, a),
3133        a)],
3135   test () :=
3136     block ([res : []],
3137       push (foo (), res),
3138       for p in [true, false] do
3139         push (bar (p), res),
3140       push (baz (), res),
3141       push (errcatch (bar ('z)), res),
3142       res),
3144   l1 : test (),
3146   translate_or_lose (foo, bar, baz),
3148   l2 : test (),
3150   is (l1 = l2));
3151 true;
3153 (kill (foo, bar, baz), 0);
3156 /* Basic tests for error checking of translated return and go forms */
3158 (foo () := return (),
3159  translate (foo));
3162 (foo () := do return (1),
3163  translate_or_lose (foo),
3164  foo ());
3167 (foo () := block (return (2)),
3168  translate_or_lose (foo),
3169  foo ());
3172 (foo () := go (x),
3173  translate (foo));
3176 (foo () := block (go (f ())),
3177  translate (foo));
3180 /* *cough* */
3181 (foo () := do (go (1), return (false), 1, return (true)),
3182  translate_or_lose (foo),
3183  foo ());
3184 true;
3186 /* *cough* */
3187 (foo () := block (block (go (x)), return (1), go (x), return (2), x, 3),
3188  translate_or_lose (foo),
3189  foo ());
3192 (foo () := block (go (end), return (0), end, 1),
3193  translate_or_lose (foo),
3194  foo ());
3197 (kill (foo), 0);
3200 /* Bug #4260: translate fails with go tag in final position */
3202 block ([translate : false, l1, l2],
3203   foo () :=
3204     [block (),
3205      block ([]),
3206      block (1),
3207      block (a),
3208      block ('a),
3209      block (done),
3210      block ('done),
3211      block (go (0), return (false), 0),
3212      block (go (a), return (false), a),
3213      block (go (done), return (false), done),
3214      block (go (b), return (false), b, 1),
3215      block (go (c), return (false), c, d),
3216      block (go (f), return (false), f, 'g),
3217      block (go (done), return (false), done, 'end),
3218      block (go (2), return (false), 1, return (true), 2, go (1))],
3220   l1 : foo (),
3222   translate_or_lose (foo),
3224   l2 : foo (),
3226   is (l1 = l2));
3227 true;
3229 (kill (foo), 0);
3232 /* We had cases of incorrect number of argument evaluations when going
3233  * through MFUNCTION-CALL internally.
3234  */
3236 (eval_string_lisp ("
3237   (makunbound '$bar)
3238   (fmakunbound '$bar)
3239   (setf (symbol-plist '$bar) '())"),
3240  0);
3243 block ([translate : false, v1, v2],
3244   foo () := block ([n : 0], bar (n : n + 1)),
3246   v1 : foo (),
3248   translate_or_lose (foo),
3250   v2 : foo (),
3252   [v2, is (v1 = v2)]);
3253 [bar (1), true];
3255 (kill (foo), 0);
3258 block ([translate : false, v1, v2],
3259   local (bar),
3261   foo () := block ([n : 0], bar (n : n + 1)),
3263   bar (q) := q,
3265   v1 : foo (),
3267   translate_or_lose (foo),
3269   v2 : foo (),
3271   [v2, is (v1 = v2)]);
3272 [1, true];
3274 (kill (foo), 0);
3277 block ([translate : false, bar, v1, v2],
3278   foo () := block ([n : 0], bar (n : n + 1)),
3280   bar : lambda ([q], q),
3282   v1 : foo (),
3284   translate_or_lose (foo),
3286   v2 : foo (), /* this used to yield 2 */
3288   [v2, is (v1 = v2)]);
3289 [1, true];
3291 (kill (foo), 0);
3294 block ([translate : false, transrun : true, v1, v2],
3295   local (bar),
3297   foo () := block ([n : 0], bar (n : n + 1), n),
3299   translate_or_lose (foo),
3301   bar ('q) := 123,
3303   v1 : foo (), /* this used to yield 1 */
3305   transrun : false,
3307   v2 : foo (),
3309   [v1, is (v1 = v2)]);
3310 [0, true];
3312 (kill (foo), 0);
3315 block ([translate : false, transrun : true, v1, v2],
3316   foo () := block ([n : 0], bar (n : n + 1), n),
3318   translate_or_lose (foo),
3320   eval_string_lisp ("(defmspec $bar (q) (declare (ignore q)) 123)"),
3322   v1 : foo (), /* this used to yield 1 */
3324   transrun : false,
3326   v2 : foo (),
3328   [v1, is (v1 = v2)]);
3329 [0, true];
3331 (kill (foo, bar),
3332  eval_string_lisp ("(setf (symbol-plist '$bar) '())"),
3333  0);
3340 /*** KILLING THESE FUNCTIONS SHOULD BE THE LAST TEST IN THIS FILE ***/
3341 (kill (translate_or_lose, compile_or_lose), 0);
3343 /*** THERE SHOULD BE NO TESTS BEYOND THIS POINT ***/