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 block ([translate : false, l1, l2],
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.
2025 block ([translate : false],
2027 foo () := (define_variable (x, 1, fixnum), x),
2028 translate_or_lose (foo),
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.
2041 block ([translate : false, l1, l2],
2044 foo () := (local (x), matchdeclare (x, true), let (a * x, x), letsimp (a * q)),
2046 /* This would yield q */
2049 translate_or_lose (foo),
2051 /* This used to yield a*q */
2054 [l2, is (l1 = l2)]);
2060 /* Rest args are now allowed in lambda expressions in MQAPPLY
2064 block ([translate : false, l1, l2],
2065 local (foo, bar, baz),
2067 /* foo used to fail to translate due to the rest arg */
2069 block ([x : 1, z : 3],
2070 lambda ([[x]], x) (x, x + 1, z)),
2072 block ([x : 2, z : 4],
2073 apply (lambda ([[x]], x), [x, x + 1, z])),
2075 block ([x : 3, z : 5],
2076 block ([f : lambda ([[x]], x)],
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
2092 block ([translate : false],
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],
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.
2126 /* Tests involving returned lambdas without free vars that were
2127 * bound during definition
2132 local (foo, bar, test),
2134 foo () := lambda ([x], 2 * x + q),
2135 bar () := lambda ([x, [y]], x * y + q),
2140 [f (3), f (5), b (2, 3, 4), b (5, 6, 7)]),
2144 translate_or_lose (foo, bar),
2148 [l2, is (l1 = l2)]);
2149 [['q + 6, 'q + 10, ['q + 6, 'q + 8], ['q + 30, 'q + 35]],
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
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),
2170 block ([f : foo (3),
2173 [f (5), b (2, 3, 4), c ()]),
2177 translate_or_lose (foo, bar, baz),
2181 [l2, is (l1 = l2)]);
2183 ['q + 'ux + 6, 'q + 'ux + 8],
2187 (kill (foo, bar, baz), 0);
2190 /* Tests involving subscripted functions. These do cause the capture
2196 local (foo, bar, baz, def, test),
2199 foo[x, y](a, b) := [x, y, a, b, q],
2200 bar[x, y](a, [b]) := [x, y, a, b, q],
2204 block ([f : foo[1, 2],
2207 [f (6, 7), b (8, 9, 10), c ()]),
2213 /* just kill and redefine */
2215 kill (foo, bar, baz),
2219 translate_or_lose (foo, bar, baz),
2223 [l2, is (l1 = l2)]);
2225 [3, 4, 8, [9, 10], 'q],
2229 (kill (foo, bar, baz), 0);
2232 /* More tests involving multiple nested lambdas */
2234 x : 'ux, y : 'uy, z : 'uz,
2236 local (foo, bar, baz, quux, def, test),
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])),
2249 block ([a : foo (1),
2253 [a (10) (11), b (12) (13), c (14) (15) (), d (16) (17)]),
2259 /* just kill and redefine */
2261 kill (foo, bar, baz, quux),
2265 translate_or_lose (foo, bar, baz, quux),
2269 [l2, is (l1 = l2)]);
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.
2284 block ([translate : false, l1, l2],
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],
2302 1.0 + if x then 0.0],
2306 for prederror in [true, false] do
2308 for x in [true, false] do
2309 push (bar (x), res),
2314 translate_or_lose (foo, bar),
2321 (kill (foo, bar), 0);
2325 * Bug #4008: translator and prederror
2328 (kill (pred, foo, bar, x, r), 0);
2331 block ([translate : false, l1, l2],
2335 [if true then q + r,
2336 if false then q + r,
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],
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),
2359 translate_or_lose (foo),
2369 block ([translate : false, l1, l2],
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]),
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),
2408 translate_or_lose (foo),
2418 block ([translate : false, l1, l2],
2419 local (test, make_fun),
2421 make_fun (name, pr) ::=
2431 pr (not x and not y),
2433 pr (not (not x and y)),
2434 pr (not (x and not y)),
2435 pr (not (not x and not y)),
2443 pr (not x or not y),
2445 pr (not (not x or y)),
2446 pr (not (x or not y)),
2447 pr (not (not x or not y))])),
2450 make_fun (bar, maybe),
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)),
2463 translate_or_lose (foo, bar),
2470 (kill (foo, bar), 0);
2473 block ([translate : false, l1, l2],
2476 pred (a, b) := equal (a, b),
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]),
2513 for prederror in [true, false] do
2516 push (foo (x, y), res),
2521 translate_or_lose (pred, foo),
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) ::=
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)),
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)),
2558 pr (not pred (x, y)),
2559 pr (not not pred (x, y)),
2560 pr (not not not pred (x, y))])),
2563 make_fun (bar, maybe),
2567 for prederror in [true, false] do
2569 for y in [1, 2] do (
2570 push (foo (x, y), res),
2571 push (bar (x, y), res)),
2576 translate_or_lose (pred, foo, bar),
2583 (kill (pred, foo, bar), 0);
2586 block ([translate : false, l1, l2],
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],
2596 for prederror in [true, false] do
2597 for x in [true, false] do
2598 push (foo (x, 17), res),
2603 translate_or_lose (foo),
2613 block ([translate : false, l1, l2],
2614 local (test, make_fun),
2616 make_fun (name, pr) ::=
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)),
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)),
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)),
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),
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)]),
2684 make_fun (bar, maybe),
2687 block ([prederror : false,
2688 l : [true, false, 1, 2.0, 'q, 'q ()],
2692 push (foo (x, y), res),
2693 push (bar (x, y), res)),
2698 translate_or_lose (foo, bar),
2705 (kill (foo, bar), 0);
2708 block ([translate : false, l1, l2],
2709 local (test, make_fun),
2711 make_fun (name, pr) ::=
2724 pr (not not (x < 1)),
2725 pr (not not (x <= 1)),
2726 pr (not not (x > 1)),
2727 pr (not not (x >= 1)),
2733 pr (not not (x = 1)),
2734 pr (not not (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))]),
2744 make_fun (bar, maybe),
2748 block ([prederror : true],
2749 push (errcatch (foo ('z)), res)),
2750 block ([prederror : false,
2754 %i, 1.0 * %i, 1.0b0 * %i,
2755 2 * %i, 2.0 * %i, 2.0b0 * %i,
2759 push (foo (x), res),
2760 push (bar (x), res))),
2765 translate_or_lose (foo, bar),
2772 (kill (foo, bar), 0);
2775 block ([translate : false, l1, l2],
2778 foo (x, q, prederror) :=
2782 if not not x then 0,
2783 if not not not x then 0,
2785 if not x then q + r,
2786 if not not x then q + r,
2787 if not not not x then q + r,
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]),
2806 block ([l : [true, false, 1, 2.0, 3.0b0, 'z, 'z ()],
2808 push (errcatch (foo (1, 2, true)), res),
2811 push (foo (x, q, false), res),
2816 translate_or_lose (foo),
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
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.
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.
2843 eqhack (interp, transl) :=
2844 if atom (interp) or atom (transl) or op (interp) # "if" or op (transl) # "if" then
2845 is (interp = transl)
2847 is (rest (interp) = rest (transl)
2849 rewritehack (first (interp)) = rewritehack (first (transl))),
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]),
2884 block ([prederror : true],
2885 push (errcatch (foo ('z)), res)),
2886 block ([prederror : false,
2890 %i, 1.0 * %i, 1.0b0 * %i,
2891 2 * %i, 2.0 * %i, 2.0b0 * %i,
2895 res : append (foo (x), res)),
2900 translate_or_lose (foo),
2904 every (eqhack, l1, l2));
2910 block ([translate : false, l1, l2],
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]),
2925 block ([l : [1, 2.0, 3.0b0, %i],
2930 push (foo (x, y, z), res),
2935 translate_or_lose (foo),
2945 block ([translate : false, l1, l2],
2949 (modedeclare (p, boolean, x, fixnum, y, flonum, z, number),
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])),
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],
2979 push (foo (p, x, y, z), res),
2984 translate_or_lose (foo),
2991 (kill (foo, p, x, y, z), 0);
2994 block ([translate : false, l1, l2],
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]),
3015 block ([prederror : false,
3016 l : [true, false, 1, 2.0, 3.0b0, %i, 'z, 'z ()],
3018 for p in [true, false] do
3022 push (foo (p, x, y, z), res),
3027 translate_or_lose (foo),
3037 block ([translate : false, l1, l2],
3040 pred (a, b) := equal (a, b),
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]),
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 ()]],
3065 push (foo (x, q), res)),
3070 translate_or_lose (pred, foo),
3077 (kill (pred, foo), 0);
3080 block ([translate : false, l1, l2],
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.
3092 for x : 1 thru 5 do a : cons (x, a),
3095 for x : 1 thru 5 while x < 3 do a : cons (x, a),
3098 for x : 1 thru 5 while x > 3 do a : cons (x, a),
3101 for x : 1 thru 5 while x < 10 do a : cons (x, a),
3104 for x : 1 thru 5 while x > 10 do a : cons (x, a),
3107 for x : 1 thru 5 unless x < 3 do a : cons (x, a),
3110 for x : 1 thru 5 unless x > 3 do a : cons (x, a),
3115 for x : 1 thru 5 while p do a : cons (x, a),
3118 for x : 1 thru 5 while x < 3 and p do a : cons (x, a),
3121 for x : 1 thru 5 while x < 3 or p do a : cons (x, a),
3124 for x : 1 thru 5 while x < 10 or 'z do a : cons (x, a),
3129 for x : 1 thru 5 do a : cons (if x then x else false, a),
3132 for x : 1 thru 5 while x < 3 do a : cons (if x then x else false, a),
3138 for p in [true, false] do
3139 push (bar (p), res),
3141 push (errcatch (bar ('z)), res),
3146 translate_or_lose (foo, bar, baz),
3153 (kill (foo, bar, baz), 0);
3156 /* Basic tests for error checking of translated return and go forms */
3158 (foo () := return (),
3162 (foo () := do return (1),
3163 translate_or_lose (foo),
3167 (foo () := block (return (2)),
3168 translate_or_lose (foo),
3176 (foo () := block (go (f ())),
3181 (foo () := do (go (1), return (false), 1, return (true)),
3182 translate_or_lose (foo),
3187 (foo () := block (block (go (x)), return (1), go (x), return (2), x, 3),
3188 translate_or_lose (foo),
3192 (foo () := block (go (end), return (0), end, 1),
3193 translate_or_lose (foo),
3200 /* Bug #4260: translate fails with go tag in final position */
3202 block ([translate : false, l1, l2],
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))],
3222 translate_or_lose (foo),
3232 /* We had cases of incorrect number of argument evaluations when going
3233 * through MFUNCTION-CALL internally.
3236 (eval_string_lisp ("
3239 (setf (symbol-plist '$bar) '())"),
3243 block ([translate : false, v1, v2],
3244 foo () := block ([n : 0], bar (n : n + 1)),
3248 translate_or_lose (foo),
3252 [v2, is (v1 = v2)]);
3258 block ([translate : false, v1, v2],
3261 foo () := block ([n : 0], bar (n : n + 1)),
3267 translate_or_lose (foo),
3271 [v2, is (v1 = v2)]);
3277 block ([translate : false, bar, v1, v2],
3278 foo () := block ([n : 0], bar (n : n + 1)),
3280 bar : lambda ([q], q),
3284 translate_or_lose (foo),
3286 v2 : foo (), /* this used to yield 2 */
3288 [v2, is (v1 = v2)]);
3294 block ([translate : false, transrun : true, v1, v2],
3297 foo () := block ([n : 0], bar (n : n + 1), n),
3299 translate_or_lose (foo),
3303 v1 : foo (), /* this used to yield 1 */
3309 [v1, is (v1 = v2)]);
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 */
3328 [v1, is (v1 = v2)]);
3332 eval_string_lisp ("(setf (symbol-plist '$bar) '())"),
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 ***/