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.
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.
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.
17 block ([translate : false],
19 make_tester (trfun) ::=
20 buildq ([trfun, name : concat (trfun, '_or_lose)],
22 block ([ret : apply ('trfun, fns), losers : []],
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))),
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.
32 ?mfunction\-delete ('name, functions))),
33 make_tester (translate),
34 make_tester (compile),
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]));
44 (translate_or_lose (foo), foo ([1, 2, 3], [a, b]));
47 /* simpler function featuring mprogn and mnot */
49 (bar (x) := (x : 2*x, x : 3*x, not (x < 100)), bar (3));
52 (translate_or_lose (bar), bar (3));
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]));
61 (translate_or_lose (try_me), try_me ([10, 9, 8, 7, 6, 5, 4, 5, 6, 7, 8, 9, 10]));
64 /* SF [ 1818645 ] Compiled maxima code containing $ARRAY gets a Lisp error. */
66 (test_array_comp (x) :=
69 for i thru 3 do (abc[i]: i*i),
71 [abc, abc[3], abc[2]]),
72 test_array_comp (100));
75 (translate_or_lose (test_array_comp), test_array_comp (100));
78 /* SF [ 545794 ] Local Array does not compile properly */
84 for i : 0 thru 7 do myvar [i] : a^i,
85 [member (myvar, arrays), listarray (myvar)]),
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.
97 [member (myvar, arrays), errcatch (listarray (myvar))];
100 /* for loop variable not special
101 * reported to mailing list 2009-08-13 "Why won't this compile?"
106 baz1 (n) := block ([S : 0], for bar1:0 thru n - 1 do S : S + foo1 (), S),
107 translate_or_lose (baz1),
111 /* original example */
113 (fun(A,b,s,VF,x,h):= block
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]),
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"
134 (f0001 (x) := [f0002 (x), f0003 (x)],
137 translate_or_lose (f0002, f0001),
141 (translate_or_lose (f0003), f0001 (1));
144 (compile_or_lose (f0003), f0001 (1));
147 (compile_or_lose (f0003, f0002, f0001), f0001 (1));
150 /* SF bug # 2938716 "too much evaluation in translated code"
153 (g0001 (x) := [g0002 (x), g0003 (x)],
156 translate_or_lose (g0002, g0001),
163 (translate_or_lose (g0003), g0001 (aa));
166 (compile_or_lose (g0003), g0001 (aa));
169 (compile_or_lose (g0003, g0002, g0001), g0001 (aa));
172 /* SF bug # 3035313 "some array references translated incorrectly"
175 (kill (aa1, aa3, bb1, bb3, cc1, cc3),
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),
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),
195 [gaa (4), gbb (4), gcc (4)];
198 [faa (4), fbb (4), fcc (4)];
201 translate_or_lose (faa, gaa, fbb, gbb, fcc, gcc);
202 [faa, gaa, fbb, gbb, fcc, gcc];
204 [gaa (4), gbb (4), gcc (4)];
207 [faa (4), fbb (4), fcc (4)];
210 compile_or_lose (faa, gaa, fbb, gbb, fcc, gcc);
211 [faa, gaa, fbb, gbb, fcc, gcc];
213 [gaa (4), gbb (4), gcc (4)];
216 [faa (4), fbb (4), fcc (4)];
219 /* try same stuff again w/ undeclared arrays ...
220 * no type spec => only one kind of array
223 (kill (aa1, aa3, bb1, bb3, cc1, cc3),
229 (translate_or_lose (faa, gaa), [gaa (4), faa (4)]);
232 (compile_or_lose (faa, gaa), [gaa (4), faa (4)]);
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),
248 [gaa (4), gbb (4), gcc (4)];
251 [faa (4), fbb (4), fcc (4)];
254 translate_or_lose (faa, gaa, fbb, gbb, fcc, gcc);
255 [faa, gaa, fbb, gbb, fcc, gcc];
257 [gaa (4), gbb (4), gcc (4)];
260 [faa (4), fbb (4), fcc (4)];
263 compile_or_lose (faa, gaa, fbb, gbb, fcc, gcc);
264 [faa, gaa, fbb, gbb, fcc, gcc];
266 [gaa (4), gbb (4), gcc (4)];
269 [faa (4), fbb (4), fcc (4)];
272 /* SF bug # 2569: "translate rat(1,x) and rat([1]) incorrect" */
274 (kill (f), f () := rat (x, x), translate_or_lose (f), f ());
277 (kill (f), f () := rat ([1]), translate_or_lose (f), f ());
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)]),
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]$
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]$
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,
315 (translate_or_lose (foo), y2a : foo (0.5), y2b : foo (1.5), 0);
324 block ([tr_float_can_branch_complex : false],
325 translate_or_lose (foo),
333 /* verify that save/compfile/compile_file/translate_file preserves upper/lower case in symbol names */
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),
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),
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]),
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/
374 if build_info()@lisp_name # "ECL" then
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),
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),
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/
401 if build_info()@lisp_name # "ECL" then
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),
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),
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/
433 if build_info()@lisp_name # "ECL" then
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")),
448 while stringp (line: readline(unlisp)) do
449 if is ("warning" = split(line, ":")[1]) then push(line, acc),
453 /* makelist translated incorrectly
454 * SF bug #3083: "Error on compiling a working maxima function"
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),
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 (
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)))))
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]]],
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)];
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 */
522 [bar(5), umm(5), mumble(5)];
525 /* mailing list 2017-03-04: "An example that is broken by compile()"
526 * translated code tickles a bug elsewhere (bug not in translator)
529 (kill(fun, trigfunc, t1),
530 fun():=block([trigfunc],
531 trigfunc:lambda([cur],cur>t1),
532 apply('trigfunc,[1])),
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.
543 (compile_or_lose(fun), fun());
546 (kill(fun, trigfunc, t1),
547 fun():=block([trigfunc],
548 trigfunc:lambda([cur],cur>t1),
549 apply(trigfunc,[1])),
556 (compile_or_lose(fun), fun());
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
564 /* no parameter list */
572 f () := lambda ([x]),
576 /* non-symbol in parameter list */
578 f () := lambda ([42], 'foo),
582 /* misplaced "rest" parameter */
584 f () := lambda ([[l], x], 'foo),
588 /* invalid "rest" parameter */
590 f () := lambda ([[l1, l2]], 'foo),
594 /* attempting to bind a constant;
595 * now OK, after commit 0517895
599 declare (c, constant),
600 f () := lambda ([c], c),
601 translate_or_lose (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?
611 f () := lambda ([x, [x]], x),
616 f () := block ([x, x:'foo], x),
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.
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));
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() ),
652 (test_f (), niceindicespref);
655 (reset (niceindicespref),
659 (translate_or_lose (test_f),
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]),
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,
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]$
718 block ([prederror : false],
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)));
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),
734 proportional_axes=xy,
737 explicit('(f(x+%i*y)),x,-2,2,y,-2,2)),
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
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],
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.
778 f(x, m) := map (lambda ([u], if m > 0 then u^m), [x, 2*x, 3*x]),
782 is (?fboundp (f) # false);
786 [f(y, 2), f(y, -2)]);
787 [[y^2, 4*y^2, 9*y^2], [false, false, false]];
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 */
799 [[y^2, 4*y^2, 9*y^2], [false, false, false]];
801 block ([prederror : false],
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.
813 (defrule (foorule, foo (), 1),
814 f () := apply2 ('(foo ()), foorule),
815 translate_or_lose (f),
819 (defrule (barrule, bar (), 2),
820 g () := applyb2 ('(bar ()), barrule),
821 translate_or_lose (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).
835 (foo () := [atan2 (-1.0, -1.0), atan2 (-1.0, 1.0)],
836 translate_or_lose (foo),
838 [-2.356194490192345, -0.7853981633974483];
840 (bar () := atan (-1.0),
841 translate_or_lose (bar),
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.
854 (foo () := [signum (0), signum (0.0),
855 signum (2), signum (2.0),
856 signum (-3), signum (-3.0)],
857 translate_or_lose (foo),
859 [0, 0.0, 1, 1.0, -1, -1.0];
864 /* The translation of declare was broken for decades. It worked
865 * under Maclisp, but it had never worked under Common Lisp.
868 (foo () := declare (n, integer, [x, y], noninteger),
869 translate_or_lose (foo),
871 [?kindp (n, integer),
872 ?kindp (n, noninteger),
874 ?kindp (x, noninteger),
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
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)]);
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.
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)],
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
927 (mode_declare (x, rational),
930 max (1.0), min (1.0),
931 max (9/10), min (9/10),
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)]),
946 translate_or_lose (foo),
951 (kill (foo, x, l1, l2), 0);
954 /* log and sqrt did not honor tr_float_can_branch_complex */
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 */
962 some (lambda ([x], freeof (%i, x)), l1));
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.
973 [every (?complexp, l2),
974 every ("#", l1, l2)]);
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.
986 every (lambda ([x, y], cabs (x - y) < 1e-15), l1, l3));
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.
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),
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.
1058 (assume (equal (a, b), notequal (c, d)),
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)),
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)))],
1083 translate_or_lose (foo),
1085 [every (lambda ([x], ?typep (x, ?boolean)), l2),
1090 (kill (foo, l1, l2),
1091 forget (equal (a, b), notequal (c, d)),
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
1100 (foo (w, x, y, z) :=
1101 (mode_declare (w, fixnum, x, float),
1110 1 / (1 + random (x))],
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))]);
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.
1133 (mode_declare (x, float),
1134 [acosh (x), asech (x), atanh (x)]),
1136 (mode_declare (x, float),
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));
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.
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))]);
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.
1163 l3 : append (foo (-3.0), foo (-2.0), bar (-0.5), bar (0.5)),
1164 every ("=", l1, l3));
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.
1177 block ([ctx : supcontext (),
1181 assume (x, y, equal (c, 0)),
1182 r : [is (a > 0), is (b < 0), is (equal (c, 0))],
1185 translate_or_lose (foo),
1187 [true, false, true];
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.
1199 block ([listarith : true],
1202 1.0 * errcatch (2.0),
1203 errcatch (error ("oops")),
1204 errcatch (?error ("oops")),
1206 translate_or_lose (foo),
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.
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));
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
1239 /* The internal LOCLIST used by local should be empty right now */
1248 translate_or_lose (foo1),
1249 block ([v : foo1 ()],
1253 (kill (f0, foo1), 0);
1256 (arr1 [0] : "three",
1258 block ([g : lambda ([],
1264 arrayinfo (arr2)])],
1266 translate_or_lose (foo2),
1267 block ([v : foo2 ()],
1270 errcatch (arrayinfo (arr2))]));
1277 (kill (arr1, foo2), 0);
1287 translate_or_lose (foo3),
1294 /* The internal LOCLIST used by local should be empty right now */
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.
1306 local (f1, f2, arr),
1310 bar (fpprintprec) :=
1319 [f1 (), f2 (), arr [1]]),
1320 [f1 (), f2 (), arr [1]]]),
1321 translate_or_lose (bar),
1323 [is (?get ('fpprintprec, '?assign) = false),
1325 [f1 (), f2 (), arr [1]]]);
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
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
1347 block ([translate : false,
1359 translate_or_lose (baz1, baz2),
1372 translate_or_lose (baz_test),
1385 /* The internal LOCLIST used by local should be empty right now */
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.
1404 compile_or_lose (foo),
1405 ?compiled\-function\-p (?symbol\-function (?get (foo, ?impl\-name))));
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.
1428 translate_or_lose (foo),
1431 translate_or_lose (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.
1439 [test1 (), test2 ()]);
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.
1453 errcatch (error_syms: 123);
1456 errcatch (error_syms: [aa, bb, 123]);
1459 error_syms: [aa, bb, cc];
1462 errcatch (niceindicespref: 123);
1465 errcatch (niceindicespref: []);
1468 niceindicespref: [aa, bb, cc];
1471 (reset (error_syms, niceindicespref), 0);
1474 /* now the example from the Stackoverflow question */
1477 "define_variable(foo, true, boolean)$
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: []],
1486 steps: endcons(list, steps),
1488 list: applyb1(list, rule_1)
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)),
1502 ([file_name_original, file_name_LISP, file_name_UNLISP, file_name_compiled]: compile_file (program_file_name), 0);
1505 stringp (file_name_compiled);
1511 (load (file_name_compiled),
1513 [["+", [["*", [1, 2, 3]], ["+", [3, 4, 6]]]],
1514 ["+", [6, ["+", [3, 4, 6]]]],
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],
1526 bar (a, b, [c]) := [a, b, c],
1535 bar (1, 2, 3, 4, 5)],
1537 /* l1: foo, bar and test are interpreted */
1540 /* l2: foo and bar are translated, and test is interpreted */
1541 translate_or_lose (foo, bar),
1544 /* l3: foo, bar and test are translated */
1545 translate_or_lose (test),
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.
1570 block ([translate : false],
1572 buildq ([r], ['r, r]),
1574 buildq ([a, b, c], ['a, a, 'b, b, 'c, c]),
1576 block ([x : 1, z : 3],
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
1588 errcatch (bar (1))],
1590 /* l1: foo, bar and test1 are interpreted */
1593 /* l2: foo and bar are translated, and test1 is interpreted */
1594 translate_or_lose (foo, bar),
1597 /* l3: foo, bar and test1 are translated */
1598 translate_or_lose (test1),
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").
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,
1629 if true then 1 else 2,
1630 if false then 1 else 2,
1632 if 1 < 2 then 'y else '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,
1644 translate_or_lose (mysignum1, mysignum2, foo),
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.
1669 (to_else_if (expr) :=
1670 if mapatom (expr) then
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))])))
1677 funmake (op, map ('to_else_if, args))),
1678 with_both_elseifs (expr) ::=
1679 buildq ([expr, texpr : to_else_if (expr)],
1684 block ([translate : false],
1699 /* l1: foo is interpreted */
1702 translate_or_lose (foo),
1704 /* l2: foo is translated
1706 * foo used to give lose3 instead of win in the elseif case.
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.
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
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).
1759 l2 : map (bar, inputs),
1764 [['negative, 'negative],
1765 ['negative, 'negative],
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.
1784 block ([translate : false],
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 */
1793 translate_or_lose (foo),
1795 /* l2: foo is translated
1797 * foo used to return [1, 1, 1]
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.
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)),
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 () ()));
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.
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]);
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.
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.
1874 block ([translate : false,
1875 use_fast_arrays : true],
1877 foo () := block ([a],
1882 /* This would correctly yield 2 */
1885 translate_or_lose (foo),
1887 /* This used to incorrectly yield wtf */
1890 [is (l1 = l2), l2]);
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.
1900 block ([translate : false],
1901 foo () := block ([a],
1903 array (a, complete, 5),
1906 /* This would correctly yield a[3] */
1909 translate_or_lose (foo),
1911 /* This would incorrectly yield a(3) */
1914 [is (l1 = l2), l2]);
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
1924 block ([translate : false],
1925 foo () := block ([a],
1927 a : make_array ('fixnum, 5),
1932 /* This would correctly yield 17 */
1935 block ([translate_fast_arrays : false],
1936 translate_or_lose (foo)),
1938 /* This would correctly yield 17 */
1941 block ([translate_fast_arrays : true],
1942 translate_or_lose (foo)),
1944 /* This would cause a lisp error */
1947 [is (l1 = l2), is (l2 = l3), l3]);
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.
1957 block ([translate : false],
1958 foo () := ["^", "^" (2, 3), apply ("^", [2, 3]),
1959 "**", "**" (2, 3), apply ("**", [2, 3])],
1961 translate_or_lose (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.
1973 (a : make_array (fixnum, 1),
1976 translate_or_lose (foo),
1977 listarray (foo ()));
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)]);
2001 /* Translating a define_variable form with translate (but not
2002 * translate_file or compfile) used to invoke undefined behavior.
2003 * This would cause a lisp error during translation under some
2004 * (but not all) lisp implementations.
2007 block ([translate : false],
2009 foo () := (define_variable (x, 1, fixnum), x),
2010 translate_or_lose (foo),
2017 /* If local was used on a matchdeclared pattern variable, and this
2018 * was all translated with something besides translate_file (e.g.,
2019 * translate, compfile, etc.), then the MATCHDECLARE property would
2020 * not be on the pattern variable.
2023 block ([translate : false, l1, l2],
2026 foo () := (local (x), matchdeclare (x, true), let (a * x, x), letsimp (a * q)),
2028 /* This would yield q */
2031 translate_or_lose (foo),
2033 /* This used to yield a*q */
2036 [l2, is (l1 = l2)]);
2042 /* Rest args are now allowed in lambda expressions in MQAPPLY
2046 block ([translate : false, l1, l2],
2047 local (foo, bar, baz),
2049 /* foo used to fail to translate due to the rest arg */
2051 block ([x : 1, z : 3],
2052 lambda ([[x]], x) (x, x + 1, z)),
2054 block ([x : 2, z : 4],
2055 apply (lambda ([[x]], x), [x, x + 1, z])),
2057 block ([x : 3, z : 5],
2058 block ([f : lambda ([[x]], x)],
2061 l1 : [foo (), bar (), baz ()],
2063 translate_or_lose (foo, bar, baz),
2065 l2 : [foo (), bar (), baz ()],
2067 [l1, is (l1 = l2)]);
2068 [[[1, 2, 3],[2, 3, 4],[3, 4, 5]], true];
2070 /* Validation has been improved for lambda expressions in MQAPPLY
2074 block ([translate : false],
2077 /* These should both fail to translate */
2078 foo () := lambda ([]) (),
2079 bar () := lambda ([x, x], x) (1, 2),
2081 translate (foo, bar));
2084 /* The translation of array functions was broken for decades */
2086 block ([translate : false, l1, l2],
2090 bar[n] := if n = 1 then 1 else n * bar[n - 1],
2092 l1 : [foo[0], foo[5], bar[5], bar[10]],
2094 translate_or_lose (foo, bar),
2096 l2 : [foo[0], foo[5], bar[5], bar[10]],
2098 [l1, is (l1 = l2)]);
2099 [[0, 5, 120, 3628800], true];
2101 (kill (foo, bar), 0);
2104 /* The translation of upward funargs (including those created by
2105 * subscripted functions) easily lead to lisp errors.
2108 /* Tests involving returned lambdas without free vars that were
2109 * bound during definition
2114 local (foo, bar, test),
2116 foo () := lambda ([x], 2 * x + q),
2117 bar () := lambda ([x, [y]], x * y + q),
2122 [f (3), f (5), b (2, 3, 4), b (5, 6, 7)]),
2126 translate_or_lose (foo, bar),
2130 [l2, is (l1 = l2)]);
2131 [['q + 6, 'q + 10, ['q + 6, 'q + 8], ['q + 30, 'q + 35]],
2134 (kill (foo, bar), 0);
2137 /* Tests involving returned lambdas with free vars that were
2138 * bound during definition. These do not cause the capture of
2145 local (foo, bar, baz, test),
2147 foo (x) := lambda ([y], x + y + q),
2148 bar (x) := lambda ([y, [z]], q + x + y * z),
2149 baz (v) := lambda ([], v),
2152 block ([f : foo (3),
2155 [f (5), b (2, 3, 4), c ()]),
2159 translate_or_lose (foo, bar, baz),
2163 [l2, is (l1 = l2)]);
2165 ['q + 'ux + 6, 'q + 'ux + 8],
2169 (kill (foo, bar, baz), 0);
2172 /* Tests involving subscripted functions. These do cause the capture
2178 local (foo, bar, baz, def, test),
2181 foo[x, y](a, b) := [x, y, a, b, q],
2182 bar[x, y](a, [b]) := [x, y, a, b, q],
2186 block ([f : foo[1, 2],
2189 [f (6, 7), b (8, 9, 10), c ()]),
2195 /* just kill and redefine */
2197 kill (foo, bar, baz),
2201 translate_or_lose (foo, bar, baz),
2205 [l2, is (l1 = l2)]);
2207 [3, 4, 8, [9, 10], 'q],
2211 (kill (foo, bar, baz), 0);
2214 /* More tests involving multiple nested lambdas */
2216 x : 'ux, y : 'uy, z : 'uz,
2218 local (foo, bar, baz, quux, def, test),
2221 /* nothing should be captured */
2222 foo (x) := lambda ([y], lambda ([z], [x, y, z])),
2223 /* x should be captured and used */
2224 bar[x](y) := lambda ([z], [x, y, z]),
2225 /* x should be captured and used */
2226 baz[x](y) := lambda ([z], lambda ([], [x, y, z])),
2227 /* nothing should be captured since x is bound by the inner lambda */
2228 quux[x](y) := lambda ([x], [x, y])),
2231 block ([a : foo (1),
2235 [a (10) (11), b (12) (13), c (14) (15) (), d (16) (17)]),
2241 /* just kill and redefine */
2243 kill (foo, bar, baz, quux),
2247 translate_or_lose (foo, bar, baz, quux),
2251 [l2, is (l1 = l2)]);
2258 (kill (foo, bar, baz, quux), 0);
2261 /* The translator was not correctly determining the mode of expressions
2262 * when a boolean mode was involved.
2264 * It was easy to get lisp errors.
2266 block ([translate : false, l1, l2],
2270 [ 1 + if true then 0,
2271 1 + if true then 0.0,
2272 1.0 + if true then 0,
2273 1.0 + if true then 0.0,
2275 1 + if false then 0,
2276 1 + if false then 0.0,
2277 1.0 + if false then 0,
2278 1.0 + if false then 0.0],
2284 1.0 + if x then 0.0],
2288 for prederror in [true, false] do
2290 for x in [true, false] do
2291 push (bar (x), res),
2296 translate_or_lose (foo, bar),
2303 (kill (foo, bar), 0);
2307 * Bug #4008: translator and prederror
2310 (kill (pred, foo, bar, x, r), 0);
2313 block ([translate : false, l1, l2],
2317 [if true then q + r,
2318 if false then q + r,
2322 if not not x then q,
2323 if not not not x then q,
2325 n + if x then q + r,
2326 n + if not x then q + r,
2327 n + if not not x then q + r,
2328 n + if not not not x then q + r],
2332 for prederror in [true, false] do
2333 for n in [1, 1.0, %i, 1.0 * %i] do
2334 for q in [1, 1.0, %i, 1.0 * %i, 'z] do
2335 for x in [true, false] do
2336 push (foo (n, q, x), res),
2341 translate_or_lose (foo),
2351 block ([translate : false, l1, l2],
2356 [if "and" () then q else r,
2357 if "and" (x) then q else r,
2358 if "and" (y) then q else r,
2359 if x and y then q else r,
2360 if not x and y then q else r,
2361 if x and not y then q else r,
2362 if not x and not y then q else r,
2363 if not (x and y) then q else r,
2364 if not (not x and y) then q else r,
2365 if not (x and not y) then q else r,
2366 if not (not x and not y) then q else r,
2368 if "or" () then q else r,
2369 if "or" (x) then q else r,
2370 if "or" (y) then q else r,
2371 if x or y then q else r,
2372 if not x or y then q else r,
2373 if x or not y then q else r,
2374 if not x or not y then q else r,
2375 if not (x or y) then q else r,
2376 if not (not x or y) then q else r,
2377 if not (x or not y) then q else r,
2378 if not (not x or not y) then q else r]),
2382 for prederror in [true, false] do
2383 for x in [true, false] do
2384 for y in [true, false] do
2385 push (foo (x, y), res),
2390 translate_or_lose (foo),
2400 block ([translate : false, l1, l2],
2401 local (test, make_fun),
2403 make_fun (name, pr) ::=
2413 pr (not x and not y),
2415 pr (not (not x and y)),
2416 pr (not (x and not y)),
2417 pr (not (not x and not y)),
2425 pr (not x or not y),
2427 pr (not (not x or y)),
2428 pr (not (x or not y)),
2429 pr (not (not x or not y))])),
2432 make_fun (bar, maybe),
2436 for prederror in [true, false] do
2437 for x in [true, false] do
2438 for y in [true, false] do (
2439 push (foo (x, y), res),
2440 push (bar (x, y), res)),
2445 translate_or_lose (foo, bar),
2452 (kill (foo, bar), 0);
2455 block ([translate : false, l1, l2],
2458 pred (a, b) := equal (a, b),
2462 [if x < y then q else r,
2463 if not (x < y) then q else r,
2464 if x <= y then q else r,
2465 if not (x <= y) then q else r,
2466 if x > y then q else r,
2467 if not (x > y) then q else r,
2468 if x >= y then q else r,
2469 if not (x >= y) then q else r,
2471 if x = y then q else r,
2472 if x # y then q else r,
2473 if not (x = y) then q else r,
2474 if not (x # y) then q else r,
2475 if not not (x = y) then q else r,
2476 if not not (x # y) then q else r,
2477 if not not not (x = y) then q else r,
2478 if not not not (x # y) then q else r,
2480 if equal (x, y) then q else r,
2481 if notequal (x, y) then q else r,
2482 if not equal (x, y) then q else r,
2483 if not not equal (x, y) then q else r,
2484 if not notequal (x, y) then q else r,
2485 if not not not equal (x, y) then q else r,
2486 if not not notequal (x, y) then q else r,
2488 if pred (x, y) then q else r,
2489 if not pred (x, y) then q else r,
2490 if not not pred (x, y) then q else r,
2491 if not not not pred (x, y) then q else r]),
2495 for prederror in [true, false] do
2498 push (foo (x, y), res),
2503 translate_or_lose (pred, foo),
2510 (kill (pred, foo), 0);
2513 block ([translate : false, l1, l2],
2514 local (test, make_fun),
2516 pred (a, b) := equal (a, b),
2518 make_fun (name, pr) ::=
2526 pr (not not (x = y)),
2527 pr (not not (x # y)),
2528 pr (not not not (x = y)),
2529 pr (not not not (x # y)),
2532 pr (not equal (x, y)),
2533 pr (notequal (x, y)),
2534 pr (not not equal (x, y)),
2535 pr (not notequal (x, y)),
2536 pr (not not not equal (x, y)),
2537 pr (not not notequal (x, y)),
2540 pr (not pred (x, y)),
2541 pr (not not pred (x, y)),
2542 pr (not not not pred (x, y))])),
2545 make_fun (bar, maybe),
2549 for prederror in [true, false] do
2551 for y in [1, 2] do (
2552 push (foo (x, y), res),
2553 push (bar (x, y), res)),
2558 translate_or_lose (pred, foo, bar),
2565 (kill (pred, foo, bar), 0);
2568 block ([translate : false, l1, l2],
2572 [if (1, 2, q, x) then q else r,
2573 if not (1, 2, q, x) then q else r,
2574 if (1, 2, q, not x) then q else r],
2578 for prederror in [true, false] do
2579 for x in [true, false] do
2580 push (foo (x, 17), res),
2585 translate_or_lose (foo),
2595 block ([translate : false, l1, l2],
2596 local (test, make_fun),
2598 make_fun (name, pr) ::=
2615 pr (not not (x and y)),
2616 pr (not not (x or y)),
2617 pr (not not not (x and y)),
2618 pr (not not not (x or y)),
2622 pr (x and not not y),
2623 pr (x or not not y),
2624 pr (not (x and not y)),
2625 pr (not (x or not y)),
2626 pr (not (x and not not y)),
2627 pr (not (x or not not y)),
2631 pr (not not x and y),
2632 pr (not 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 (not x and not y),
2639 pr (not x or not y),
2640 pr (not (not x and not y)),
2641 pr (not (not x or not y)),
2647 pr (x > 1 and not y),
2648 pr (x > 1 or not y),
2649 pr (not x > 1 and y),
2650 pr (not x > 1 or y),
2651 pr (not x > 1 and not y),
2652 pr (not x > 1 or not y),
2658 pr (x and not y <= 1),
2659 pr (x or not y <= 1),
2660 pr (not x and y <= 1),
2661 pr (not x or y <= 1),
2662 pr (not x and not y <= 1),
2663 pr (not x or not y <= 1)]),
2666 make_fun (bar, maybe),
2669 block ([prederror : false,
2670 l : [true, false, 1, 2.0, 'q, 'q ()],
2674 push (foo (x, y), res),
2675 push (bar (x, y), res)),
2680 translate_or_lose (foo, bar),
2687 (kill (foo, bar), 0);
2690 block ([translate : false, l1, l2],
2691 local (test, make_fun),
2693 make_fun (name, pr) ::=
2706 pr (not not (x < 1)),
2707 pr (not not (x <= 1)),
2708 pr (not not (x > 1)),
2709 pr (not not (x >= 1)),
2715 pr (not not (x = 1)),
2716 pr (not not (x # 1)),
2719 pr (notequal (x, 1)),
2720 pr (not equal (x, 1)),
2721 pr (not notequal (x, 1)),
2722 pr (not not equal (x, 1)),
2723 pr (not not notequal (x, 1))]),
2726 make_fun (bar, maybe),
2730 block ([prederror : true],
2731 push (errcatch (foo ('z)), res)),
2732 block ([prederror : false,
2736 %i, 1.0 * %i, 1.0b0 * %i,
2737 2 * %i, 2.0 * %i, 2.0b0 * %i,
2741 push (foo (x), res),
2742 push (bar (x), res))),
2747 translate_or_lose (foo, bar),
2754 (kill (foo, bar), 0);
2757 block ([translate : false, l1, l2],
2760 foo (x, q, prederror) :=
2764 if not not x then 0,
2765 if not not not x then 0,
2767 if not x then q + r,
2768 if not not x then q + r,
2769 if not not not x then q + r,
2771 if not x then 1 else 2,
2772 if not not x then 1 else 2,
2773 if not not not x then 1 else 2,
2774 if x then x else q + r,
2775 if not x then x else q + r,
2776 if not not x then x else q + r,
2777 if not not not x then x else q + r,
2778 if x = 1 then x else q + r,
2779 if x # 1 then x else q + r,
2780 if not x = 1 then x else q + r,
2781 if not x # 1 then x else q + r,
2782 if not not x = 1 then x else q + r,
2783 if not not x # 1 then x else q + r,
2784 if not not not x = 1 then x else q + r,
2785 if not not not x # 1 then x else q + r]),
2788 block ([l : [true, false, 1, 2.0, 3.0b0, 'z, 'z ()],
2790 push (errcatch (foo (1, 2, true)), res),
2793 push (foo (x, q, false), res),
2798 translate_or_lose (foo),
2808 block ([translate : false, l1, l2],
2809 local (rewritehack, eqhack, test),
2811 /* Take a relational expr and potentially rewrite it in some
2812 * equivalent way, e.g. x<1 => 1-x>0
2815 eval_string_lisp ("(apply #'mevalp2 $r (mop $r) (margs $r))")[1],
2817 /* Translated code can produce relational exprs that are in a
2818 * different, but equivalent, form compared to the exprs produce
2819 * by interpreted code.
2821 * Compare two conditionals by requiring that everything matches
2822 * exactly, except possibly the first (only) test. The tests
2823 * should match exactly after applying rewritehack to them.
2825 eqhack (interp, transl) :=
2826 if atom (interp) or atom (transl) or op (interp) # "if" or op (transl) # "if" then
2827 is (interp = transl)
2829 is (rest (interp) = rest (transl)
2831 rewritehack (first (interp)) = rewritehack (first (transl))),
2835 [if x < 1 then x else r,
2836 if x <= 1 then x else r,
2837 if x > 1 then x else r,
2838 if x >= 1 then x else r,
2840 if not (x < 1) then x else r,
2841 if not (x <= 1) then x else r,
2842 if not (x > 1) then x else r,
2843 if not (x >= 1) then x else r,
2845 if not not (x < 1) then x else r,
2846 if not not (x <= 1) then x else r,
2847 if not not (x > 1) then x else r,
2848 if not not (x >= 1) then x else r,
2850 if x = 1 then x else r,
2851 if x # 1 then x else r,
2852 if not (x = 1) then x else r,
2853 if not (x # 1) then x else r,
2854 if not not (x = 1) then x else r,
2855 if not not (x # 1) then x else r,
2857 if equal (x, 1) then x else r,
2858 if notequal (x, 1) then x else r,
2859 if not equal (x, 1) then x else r,
2860 if not notequal (x, 1) then x else r,
2861 if not not equal (x, 1) then x else r,
2862 if not not notequal (x, 1) then x else r]),
2866 block ([prederror : true],
2867 push (errcatch (foo ('z)), res)),
2868 block ([prederror : false,
2872 %i, 1.0 * %i, 1.0b0 * %i,
2873 2 * %i, 2.0 * %i, 2.0b0 * %i,
2877 res : append (foo (x), res)),
2882 translate_or_lose (foo),
2886 every (eqhack, l1, l2));
2892 block ([translate : false, l1, l2],
2897 [if x > 0 and y > 0 and z > 0 then x + y = z else r,
2898 if x > 0 or y > 0 or z > 0 then x + y = z else r,
2899 if x >= 1 and y >= 1 and z >= 1 then x + y = z else r,
2900 if x >= 1 or y >= 1 or z >= 1 then x + y = z else r,
2901 if x <= 2 and y <= 2 and z <= 2 then x + y = z else r,
2902 if x <= 2 or y <= 2 or z <= 2 then x + y = z else r,
2903 if x < 3 and y < 3 and z < 3 then x + y = z else r,
2904 if x < 3 or y < 3 or z < 3 then x + y = z else r]),
2907 block ([l : [1, 2.0, 3.0b0, %i],
2912 push (foo (x, y, z), res),
2917 translate_or_lose (foo),
2927 block ([translate : false, l1, l2],
2931 (modedeclare (p, boolean, x, fixnum, y, flonum, z, number),
2933 [if p and x > 0 and y > 0 and z > 0 then x + y - z else r,
2934 if p or x > 0 or y > 0 or z > 0 then x + y - z else r,
2935 if p and x >= 1 and y >= 1 and z >= 1 then x + y - z else r,
2936 if p or x >= 1 or y >= 1 or z >= 1 then x + y - z else r,
2937 if p and x <= 2 and y <= 2 and z <= 2 then x + y - z else r,
2938 if p or x <= 2 or y <= 2 or z <= 2 then x + y - z else r,
2939 if p and x < 3 and y < 3 and z < 3 then x + y - z else r,
2940 if p or x < 3 or y < 3 or z < 3 then x + y - z else r,
2942 if p and x > y and y > z and z > 3 then x + y + z else r,
2943 if p or x > y or y > z or z > 3 then x + y + z else r,
2944 if p and x >= y and y >= z and z >= 2 then x + y + z else r,
2945 if p or x >= y or y >= z or z >= 2 then x + y + z else r,
2946 if p and x <= y and y <= z and z <= 1 then x + y + z else r,
2947 if p or x <= y or y <= z or z <= 1 then x + y + z else r,
2948 if p and x < y and y < z and z < 0 then x + y + z else r,
2949 if p or x < y or y < z or z < 0 then x + y + z else r])),
2952 block ([bool : [true, false],
2953 fixl : [0, 1, 2, 3, 4],
2954 flol : [0.0, 1.0, 2.0, 3.0, 4.0],
2955 numl : [0, 1.0, 2, 3.0, 4],
2961 push (foo (p, x, y, z), res),
2966 translate_or_lose (foo),
2973 (kill (foo, p, x, y, z), 0);
2976 block ([translate : false, l1, l2],
2981 [if p and x and y and z then x + y = z else r,
2982 if p or x or y or z then x + y = z else r,
2984 if p and equal (x, 1) and equal (y, 1) and equal (z, 1) then x + y = z else r,
2985 if p or equal (x, 1) or equal (y, 1) or equal (z, 1) then x + y = z else r,
2987 if not p and not equal (x, 1) and not equal (y, 1) and not equal (z, 1) then x + y = z else r,
2988 if not p or not equal (x, 1) or not equal (y, 1) or not equal (z, 1) then x + y = z else r,
2990 if p and notequal (x, 1) and notequal (y, 1) and notequal (z, 1) then x + y = z else r,
2991 if p or notequal (x, 1) or notequal (y, 1) or notequal (z, 1) then x + y = z else r,
2993 if not p and not notequal (x, 1) and not notequal (y, 1) and not notequal (z, 1) then x + y = z else r,
2994 if not p or not notequal (x, 1) or not notequal (y, 1) or not notequal (z, 1) then x + y = z else r]),
2997 block ([prederror : false,
2998 l : [true, false, 1, 2.0, 3.0b0, %i, 'z, 'z ()],
3000 for p in [true, false] do
3004 push (foo (p, x, y, z), res),
3009 translate_or_lose (foo),
3019 block ([translate : false, l1, l2],
3022 pred (a, b) := equal (a, b),
3025 block ([r, var1, var2, v1 : 'var1, v2 : 'var2],
3026 [if pred (x, 1) then x,
3027 if not pred (x, 1) then x,
3028 if pred (x, 1) or pred (x, 2) then x,
3029 if pred (x, 1) then x else q + r,
3030 if not pred (x, 1) then x else q + r,
3031 if pred (x, 1) or pred (x, 2) then x else q + r,
3032 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,
3033 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,
3034 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,
3035 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,
3036 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,
3037 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]),
3041 block ([prederror : false],
3042 push (errcatch (foo (true, false)), res)),
3043 block ([prederror : false,
3044 l : [true, false, 1, 2.0, 3.0b0, %i, 'z, 'z ()]],
3047 push (foo (x, q), res)),
3052 translate_or_lose (pred, foo),
3059 (kill (pred, foo), 0);
3062 block ([translate : false, l1, l2],
3065 /* I really want push(x,a) below in foo, bar and baz,
3066 * but the translation of the push special form just
3067 * punts to MEVAL. I want the loop bodies translated
3068 * better than that, especially in baz, so just do
3069 * a:cons(x,a) everywhere here.
3074 for x : 1 thru 5 do a : cons (x, a),
3077 for x : 1 thru 5 while x < 3 do a : cons (x, a),
3080 for x : 1 thru 5 while x > 3 do a : cons (x, a),
3083 for x : 1 thru 5 while x < 10 do a : cons (x, a),
3086 for x : 1 thru 5 while x > 10 do a : cons (x, a),
3089 for x : 1 thru 5 unless x < 3 do a : cons (x, a),
3092 for x : 1 thru 5 unless x > 3 do a : cons (x, a),
3097 for x : 1 thru 5 while p do a : cons (x, a),
3100 for x : 1 thru 5 while x < 3 and p do a : cons (x, a),
3103 for x : 1 thru 5 while x < 3 or p do a : cons (x, a),
3106 for x : 1 thru 5 while x < 10 or 'z do a : cons (x, a),
3111 for x : 1 thru 5 do a : cons (if x then x else false, a),
3114 for x : 1 thru 5 while x < 3 do a : cons (if x then x else false, a),
3120 for p in [true, false] do
3121 push (bar (p), res),
3123 push (errcatch (bar ('z)), res),
3128 translate_or_lose (foo, bar, baz),
3135 (kill (foo, bar, baz), 0);
3138 /* Basic tests for error checking of translated return and go forms */
3140 (foo () := return (),
3144 (foo () := do return (1),
3145 translate_or_lose (foo),
3149 (foo () := block (return (2)),
3150 translate_or_lose (foo),
3158 (foo () := block (go (f ())),
3163 (foo () := do (go (1), return (false), 1, return (true)),
3164 translate_or_lose (foo),
3169 (foo () := block (block (go (x)), return (1), go (x), return (2), x, 3),
3170 translate_or_lose (foo),
3174 (foo () := block (go (end), return (0), end, 1),
3175 translate_or_lose (foo),
3182 /* Bug #4260: translate fails with go tag in final position */
3184 block ([translate : false, l1, l2],
3193 block (go (0), return (false), 0),
3194 block (go (a), return (false), a),
3195 block (go (done), return (false), done),
3196 block (go (b), return (false), b, 1),
3197 block (go (c), return (false), c, d),
3198 block (go (f), return (false), f, 'g),
3199 block (go (done), return (false), done, 'end),
3200 block (go (2), return (false), 1, return (true), 2, go (1))],
3204 translate_or_lose (foo),
3218 /*** KILLING THESE FUNCTIONS SHOULD BE THE LAST TEST IN THIS FILE ***/
3219 (kill (translate_or_lose, compile_or_lose), 0);
3221 /*** THERE SHOULD BE NO TESTS BEYOND THIS POINT ***/