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), plog (x), cos (x), cot (x), csc (x),
285 sinh (x), csch (x), sqrt (x), exp (x), atan2 (11, x), atan2 (x, 2/3)]),
290 [.4621171572600097,.5463024898437905,0.886818883970074,1.139493927324549,
291 1.047197551196597,1.107148717794091,0.479425538604203,
292 1.570796326794897-1.316957896924817*%i,.4812118250596035,1.44363547517881,
293 1.127625965206381,2.163953413738653,0.5,1.316957896924817*%i,
294 0.523598775598299,.5204998778130465,-.6931471805599453,-.6931471805599453,
295 .8775825618903728,1.830487721712452,2.085829642933488,.5210953054937474,
296 1.919034751334944,.7071067811865476,1.648721270700128,1.5253730473733196,
300 [.9051482536448664,14.10141994717172,.4250960349422805,14.1368329029699,
301 .9624236501192069*%i,.5880026035475675,.9974949866040544,.7297276562269662,
302 1.194763217287109,.6251451172504168,2.352409615243247,1.104791392982512,1.5,
303 .8410686705679303,1.570796326794897-.9624236501192069*%i,.9661051464753108,
304 .4054651081081644,.4054651081081644,0.0707372016677029,.07091484430265245,
305 1.002511304246725,2.129279455094817,.4696424405952246,1.224744871391589,
306 4.481689070338065,1.4352686128093959,1.1525719972156676]$
309 [0.7615941559557649,1.557407724654902,0.6480542736638855,
310 1.850815717680925,0.0,0.7853981633974483,0.8414709848078965,
311 1.570796326794897,0.881373587019543,0.881373587019543,
312 1.543080634815244,1.313035285499331,1.0,0.0,1.570796326794897,
313 0.8427007929497148,0.0,0.0,0.5403023058681398,0.6420926159343306,
314 1.188395105778121,1.175201193643801,0.8509181282393216,1.0,
315 2.718281828459045,1.4801364395941514,0.982793723247329]$
317 (translate_or_lose (foo), y2a : foo (0.5), y2b : foo (1.5), 0);
326 block ([tr_float_can_branch_complex : false],
327 translate_or_lose (foo),
335 /* verify that save/compfile/compile_file/translate_file preserves upper/lower case in symbol names */
340 foo (x) := my_foo * x,
341 Foo (x) := my_Foo * x,
342 FOO (x) := my_FOO * x,
343 [my_foo, my_Foo, my_FOO] : [123, 456, 789],
344 results : [foo (2), Foo (3), FOO (4)],
345 my_test () := is (results = [2*123, 3*456, 4*789]),
346 lisp_name : ssubst ("_", " ", build_info()@lisp_name),
347 lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-save-", lisp_name, ".lisp"),
348 save (lisp_filename, values, functions),
349 kill (allbut (lisp_filename)),
350 load (lisp_filename),
357 foo (x) := my_foo * x,
358 Foo (x) := my_Foo * x,
359 FOO (x) := my_FOO * x,
360 lisp_name : ssubst ("_", " ", build_info()@lisp_name),
361 lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compfile-", lisp_name, ".lisp"),
362 compfile (lisp_filename, functions),
364 load (lisp_filename),
365 [my_foo, my_Foo, my_FOO] : [123, 456, 789],
366 results : [foo (2), Foo (3), FOO (4)],
367 my_test () := is (results = [2*123, 3*456, 4*789]),
373 /* skip this test (and fail) if Lisp = ECL because stream i/o causes "stack smashing" error
374 * see: https://sourceforge.net/p/maxima/bugs/3291/
376 if build_info()@lisp_name # "ECL" then
378 lisp_name : ssubst ("_", " ", build_info()@lisp_name),
379 maxima_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compile_file-", lisp_name, ".mac"),
380 fasl_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compile_file-", lisp_name, ".fasl"),
381 lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-compile_file-", lisp_name, ".LISP"),
382 maxima_output : openw (maxima_filename),
384 "foo (x) := my_foo * x;
385 Foo (x) := my_Foo * x;
386 FOO (x) := my_FOO * x;
387 [my_foo, my_Foo, my_FOO] : [123, 456, 789];
388 results : [foo (2), Foo (3), FOO (4)];
389 my_test () := is (results = [2*123, 3*456, 4*789]);",
390 printf (maxima_output, maxima_content),
391 close (maxima_output),
392 compile_file (maxima_filename, fasl_filename, lisp_filename),
393 kill (allbut (lisp_filename)),
394 load (lisp_filename),
400 /* skip this test (and fail) if Lisp = ECL because stream i/o causes "stack smashing" error
401 * see: https://sourceforge.net/p/maxima/bugs/3291/
403 if build_info()@lisp_name # "ECL" then
405 lisp_name : ssubst ("_", " ", build_info()@lisp_name),
406 maxima_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-translate_file-", lisp_name, ".mac"),
407 lisp_filename : sconcat (maxima_tempdir, "/tmp-rtest_translator-translate_file-", lisp_name, ".LISP"),
408 maxima_output : openw (maxima_filename),
410 "foo (x) := my_foo * x;
411 Foo (x) := my_Foo * x;
412 FOO (x) := my_FOO * x;
413 [my_foo, my_Foo, my_FOO] : [123, 456, 789];
414 results : [foo (2), Foo (3), FOO (4)];
415 my_test () := is (results = [2*123, 3*456, 4*789]);",
416 printf (maxima_output, maxima_content),
417 close (maxima_output),
418 translate_file (maxima_filename, lisp_filename),
419 kill (allbut (lisp_filename)),
420 load (lisp_filename),
426 Translating a literal exponent that comes out as a float shouldn't
427 produce assigned type any. This test runs the translation for a
428 trivial function that triggered the bug then looks in the unlisp
429 file (which contains messages from the translator) and checks that
430 there aren't any warnings.
432 /* skip this test (and fail) if Lisp = ECL because stream i/o causes "stack smashing" error
433 * see: https://sourceforge.net/p/maxima/bugs/3291/
435 if build_info()@lisp_name # "ECL" then
437 lisp_name : ssubst ("_", " ", build_info()@lisp_name),
438 basename: sconcat (maxima_tempdir, "/tmp-rtest_translator-2934-", lisp_name),
439 maxima_filename : sconcat (basename, ".mac"),
440 lisp_filename : sconcat (basename, ".LISP"),
441 maxima_output : openw (maxima_filename),
442 maxima_content : "f () := block([y], mode_declare(y,float), y: 3^0.33, y)$",
443 printf (maxima_output, maxima_content),
444 close (maxima_output),
445 translate_file (maxima_filename, lisp_filename),
446 kill (allbut(basename)),
447 /* Any warning messages end up at .UNLISP */
448 block ([unlisp: openr (sconcat (basename, ".UNLISP")),
450 while stringp (line: readline(unlisp)) do
451 if is ("warning" = split(line, ":")[1]) then push(line, acc),
455 /* makelist translated incorrectly
456 * SF bug #3083: "Error on compiling a working maxima function"
460 f1(n) := makelist (1, n),
461 f2(n) := makelist (i^2, i, n),
462 f3(l) := makelist (i^3, i, l),
463 f4(n) := makelist (i^4, i, 1, n),
464 f5(m, n) := makelist (i^5, i, 1, n, m),
465 translate_or_lose(f1, f2, f3, f4, f5),
482 [1, 243, 3125, 16807, 59049];
484 /* original function from bug report */
486 (ordersort(lis,vars,oper):=block([negsumdispflag:false,liss:lis,varlist:vars,temp], /*Does lexicographical sort */
487 for i:1 thru length(varlist) do (
489 liss:sort(liss,lambda([x,y],apply("and",map(oper,makelist(part(x,2)[k],k,1,i)
490 ,makelist(part(y,2)[k],k,1,i)))))
492 translate_or_lose (ordersort),
493 [member ('transfun, properties (ordersort)),
494 ordersort([[-7,[0,2,1]],[3,[1,2,1]],[1,[0,4,1]],[6,[4,3,3]],[6,[4,4,3]],
495 [-7,[3,5,4]],[2,[0,0,5]],[-10,[2,2,5]],[-10,[3,4,7]],[7,[3,8,9]]],
499 [[6,[4,4,3]],[6,[4,3,3]],[7,[3,8,9]],[-7,[3,5,4]],[-10,[3,4,7]],
500 [-10,[2,2,5]],[3,[1,2,1]],[1,[0,4,1]],[-7,[0,2,1]],[2,[0,0,5]]]];
502 /* 'define' translated incorrectly, reported to mailing list circa 2017-01-24 */
504 (kill(foo, bar, baz, quux, mumble, blurf, umm, f, x, y),
505 foo(y) := define(bar(x), x + y),
506 baz(f, y) := define(funmake(f, [x]), x + y),
507 quux() := (mumble(x) := 1 + x),
508 [foo(10), baz(blurf, 20), quux()]);
509 /* note that results match because rhs of ":=" isn't simplified */
510 [bar(x) := 10 + x, blurf(x) := 20 + x, mumble(x) := 1 + x];
512 [bar(5), blurf(5), mumble(5)];
515 (kill(bar, blurf, mumble),
516 translate_or_lose(foo, baz, quux),
517 [foo(11), baz(umm, 21), quux()]);
518 /* note that results match because rhs of ":=" isn't simplified */
519 [bar(x) := 11 + x, umm(x) := 21 + x, mumble(x) := 1 + x];
521 makelist (is (x # false), x, map (?fboundp, [foo, baz, quux])); /* test for generalized Boolean value */
524 [bar(5), umm(5), mumble(5)];
527 /* mailing list 2017-03-04: "An example that is broken by compile()"
528 * translated code tickles a bug elsewhere (bug not in translator)
531 (kill(fun, trigfunc, t1),
532 fun():=block([trigfunc],
533 trigfunc:lambda([cur],cur>t1),
534 apply('trigfunc,[1])),
538 /* I (Robert Dodier) believe this result should be trigfunc(1),
539 * but, in any event, interpreted and compiled code should agree.
540 * But if MAPPLY1 is ever changed, we can adjust these results.
545 (compile_or_lose(fun), fun());
548 (kill(fun, trigfunc, t1),
549 fun():=block([trigfunc],
550 trigfunc:lambda([cur],cur>t1),
551 apply(trigfunc,[1])),
558 (compile_or_lose(fun), fun());
561 /* Verify that we catch malformed lambda expressions during translation.
562 * More checks need to be added to the translator and more tests need to
566 /* no parameter list */
574 f () := lambda ([x]),
578 /* non-symbol in parameter list */
580 f () := lambda ([42], 'foo),
584 /* misplaced "rest" parameter */
586 f () := lambda ([[l], x], 'foo),
590 /* invalid "rest" parameter */
592 f () := lambda ([[l1, l2]], 'foo),
596 /* attempting to bind a constant;
597 * now OK, after commit 0517895
601 declare (c, constant),
602 f () := lambda ([c], c),
603 translate_or_lose (f))$
606 /* Verify that parameter/variable lists cannot contain duplicate variables.
608 * We only test a couple of cases here. Many more tests for non-translated
609 * code are in rtest2. Do we want to test them all here as well?
613 f () := lambda ([x, [x]], x),
618 f () := block ([x, x:'foo], x),
622 /* ensure that a null OPERATORS property doesn't interfere with
623 * translation of local variable used as a function name.
624 * This is the bug that caused failures in rtest_fractals when executed after run_testsuite.
627 (kill(aa, foobarbaz, mumbleblurf, hhh),
628 matchdeclare (aa, all),
629 tellsimp (mumbleblurf(aa), 1 - aa),
630 kill (mumbleblurf), /* as of 2018-01-28, this leaves (OPERATORS NIL) in property list */
631 hhh(mumbleblurf, u) := mumbleblurf(u),
632 foobarbaz(x) := 100 + x,
633 translate_or_lose (hhh),
634 hhh (foobarbaz, 11));
637 /* SF bug report #3402: "Unbinding defined variable generates error in compiled functions" */
639 define_variable (zorble, 0, fixnum);
642 (kill(f), f() := block ([zorble], 42), f());
645 (translate_or_lose(f), f());
648 /* bug reported to mailing list 2018-12-03: "error in compiling function with global variable" */
650 (test_f():= block( [a,b,c,d], niceindicespref:[a,b,c,d], disp("ciao"), return() ),
654 (test_f (), niceindicespref);
657 (reset (niceindicespref),
661 (translate_or_lose (test_f),
666 (reset (niceindicespref), 0);
669 /* additional tests with variables which have ASSIGN property */
671 (set_error_stuff_permanently () :=
672 block (error_syms : '[myerr1, myerr2, myerr3], error_size : 40),
673 set_error_stuff_temporarily() :=
674 block([error_syms : '[myerror1, myerror2, myerror3], error_size : 55],
675 [error_syms, error_size]),
679 (reset (error_syms, error_size),
680 set_error_stuff_permanently (),
681 [error_syms, error_size]);
682 [[myerr1, myerr2, myerr3], 40];
684 (reset (error_syms, error_size),
685 translate_or_lose (set_error_stuff_permanently),
686 set_error_stuff_permanently (),
687 [error_syms, error_size]);
688 [[myerr1, myerr2, myerr3], 40];
690 (reset (error_syms, error_size),
691 set_error_stuff_temporarily());
692 [[myerror1, myerror2, myerror3], 55];
694 [error_syms, error_size];
695 [[errexp1, errexp2, errexp3], 60];
697 (translate_or_lose (set_error_stuff_temporarily),
698 set_error_stuff_temporarily());
699 [[myerror1, myerror2, myerror3], 55];
701 [error_syms, error_size];
702 [[errexp1, errexp2, errexp3], 60];
704 (kill(all), reset(), 0);
707 /* SF bug #3412: "Bug when translating functions that contain an \"if\" (in my case an implicit if)" */
708 /* Bug #4008: translator and prederror */
710 (f(x):=if cabs(1/(x+1)) < 1 then 1/(x+1) else 1,
712 if 1/sqrt(y^2+(x+1)^2) < 1 then 1/(%i*y+x+1) else 1;
714 makelist (f(xy[1] + %i*xy[2]), xy, [[0, 0], [0, 1], [1, 1], [1, 0], [0, 2], [2, 2], [2, 0]]);
715 [1, 1/(%i+1), 1/(%i+2), 1/2, 1/(2*%i+1), 1/(2*%i+3), 1/3]$
720 block ([prederror : false],
722 if 1 - 1/sqrt(y^2+(x+1)^2) > 0 then 1/(%i*y+x+1) else 1;
724 block ([prederror : true],
725 errcatch (f(x + %i*y)));
731 makelist (f(xy[1] + %i*xy[2]), xy, [[0, 0], [0, 1], [1, 1], [1, 0], [0, 2], [2, 2], [2, 0]]);
732 [1, 1/(%i+1), 1/(%i+2), 1/2, 1/(2*%i+1), 1/(2*%i+3), 1/3]$
734 (if draw_version = 'draw_version then load (draw),
736 proportional_axes=xy,
739 explicit('(f(x+%i*y)),x,-2,2,y,-2,2)),
743 /* nested if example -- note top-level "if" doesn't have an "else" clause, so the result is sometimes 'false' */
745 (g(a, b, c) := if a + b > c
756 (aa: [3,9/4,5/4,11/4,1,0,9/4,1/4,5/2,9/4,3,5/2],
757 bb: [3/2,3,1/4,3/4,5/2,7/4,5/2,3/4,1/2,3,13/4,7/2],
758 cc: [7/2,15/4,5/2,5/4,15/4,1,1/4,7/4,2,11/4,1/4,7/4],
759 map (g, aa, bb, cc));
760 [3/2,9/8,false,3/4,false,0,5,false,-4,9/8,13/2,31/4]$
762 (translate_or_lose (g),
763 map (g, aa, bb, cc));
764 [3/2,9/8,false,3/4,false,0,5,false,-4,9/8,13/2,31/4]$
766 block ([prederror : false],
768 ''(if 2 - z > 0 then (if 1 > z then (if 1 > z then z + 2 elseif 1 > z / 2 then -z else -z) else 1/2));
770 block ([prederror : true],
771 errcatch (g (1, 1, z)));
774 /* SF bug #3556: "5.43.0 translate / compile error"
775 * Ensure that "if" within lambda is translated correctly.
776 * The fix for #3412 tickled this bug.
780 f(x, m) := map (lambda ([u], if m > 0 then u^m), [x, 2*x, 3*x]),
784 is (?fboundp (f) # false);
788 [f(y, 2), f(y, -2)]);
789 [[y^2, 4*y^2, 9*y^2], [false, false, false]];
792 errcatch (f(10, n)));
793 /* ensure that conditional expressions get simplified to expunge $FALSE ... sigh. */
794 ''([[if n > 0 then 10^n, if n > 0 then 20^n, if n > 0 then 30^n]]);
796 (translate_or_lose (f),
797 is (?fboundp (f) # false)); /* test for generalized Boolean value */
801 [[y^2, 4*y^2, 9*y^2], [false, false, false]];
803 block ([prederror : false],
805 ''([if n > 0 then 10^n, if n > 0 then 20^n, if n > 0 then 30^n]);
807 block ([prederror : true],
808 errcatch (f(10, n)));
811 /* apply2 was translated incorrectly for several years. applyb2
812 * was translated incorrectly for decades.
815 (defrule (foorule, foo (), 1),
816 f () := apply2 ('(foo ()), foorule),
817 translate_or_lose (f),
821 (defrule (barrule, bar (), 2),
822 g () := applyb2 ('(bar ()), barrule),
823 translate_or_lose (g),
827 (kill (foorule, f, barrule, g), 0);
830 /* atan and atan2 calls with float arguments were translated
831 * incorrectly for over a decade. atan always caused a lisp error
832 * and atan2 had a range between 0 and 2*%pi that was inconsistent
833 * with the interpreted and non-float cases (where the range is
834 * between -%pi and %pi).
837 (foo () := [atan2 (-1.0, -1.0), atan2 (-1.0, 1.0)],
838 translate_or_lose (foo),
840 [-2.356194490192345, -0.7853981633974483];
842 (bar () := atan (-1.0),
843 translate_or_lose (bar),
847 (kill (foo, bar), 0);
850 /* The translation of a signum call with a float argument was
851 * inconsistent when compared to the interpreted case and other
852 * translated cases. signum should return an integer or a float
853 * when given an integer or a float argument, respectively.
856 (foo () := [signum (0), signum (0.0),
857 signum (2), signum (2.0),
858 signum (-3), signum (-3.0)],
859 translate_or_lose (foo),
861 [0, 0.0, 1, 1.0, -1, -1.0];
866 /* The translation of declare was broken for decades. It worked
867 * under Maclisp, but it had never worked under Common Lisp.
870 (foo () := declare (n, integer, [x, y], noninteger),
871 translate_or_lose (foo),
873 [?kindp (n, integer),
874 ?kindp (n, noninteger),
876 ?kindp (x, noninteger),
878 ?kindp (y, noninteger)]);
879 [true, false, false, true, false, true];
881 (kill (foo, n, x, y), 0);
884 /* If a variable was declared to be of mode rational, then a lisp
885 * error could occur during translation when attempting to convert
889 (foo (x) := (mode_declare (x, rational), float (x)),
890 bar (y) := (mode_declare (y, rational), 1.0 + y),
891 translate_or_lose (foo, bar),
892 [foo (1/4), bar (1/2)]);
895 (kill (foo, bar, x, y), 0);
898 /* The translation of an atan2 call with one float and one rational
899 * argument was broken because the rational was not converted to a
900 * float before calling ATAN.
908 bar (y, x) := (mode_declare (x, float, y, rational), atan2 (y, x)),
909 l1 : [foo (), bar (1/3, 0.0)],
910 translate_or_lose (foo, bar),
911 l2 : [foo (), bar (1/3, 0.0)],
915 (kill (foo, bar, x, y, l1, l2), 0);
918 /* When attempting to apply float contagion to the arguments, some
919 * translations of max and min with mixed float and rational arguments
920 * were broken because the rationals were not converted to floats before
921 * calling MAX or MIN (like atan2 above). Also, due to implementation-
922 * dependent behavior in the underlying lisp regarding what to return
923 * from MAX and MIN, the wrong mode could be used during translation and
924 * some of the translations were possibly inconsistent with interpreted
929 (mode_declare (x, rational),
932 max (1.0), min (1.0),
933 max (9/10), min (9/10),
935 max (0.0, 1), min (0.0, 1),
936 max (0, 1), min (0, 1),
937 max (1.0, 1), min (1.0, 1),
938 max (1, 1.0), min (1, 1.0),
939 max (2.0, 3.0), min (2.0, 3.0),
940 max (-1, 1/2), min (-1, 1/2),
941 max (3/4, 1/2), min (3/4, 1/2),
942 max (0.0, 1/2), min (0.0, 1/2),
943 max (0, x), min (0, x),
944 max (-1.0, x), min (-1.0, x),
945 max (5/6, x), min (5/6, x),
946 max (x, 1), min (x, 1)]),
948 translate_or_lose (foo),
953 (kill (foo, x, l1, l2), 0);
956 /* log and sqrt did not honor tr_float_can_branch_complex */
959 (mode_declare (x, float),
960 [log (-1.0), log (x),
961 sqrt (-1.0), sqrt (x)]),
962 /* l1 is a list of Maxima complex numbers */
964 some (lambda ([x], freeof (%i, x)), l1));
967 block ([tr_float_can_branch_complex : false],
968 translate_or_lose (foo),
969 /* l2 is a list of lisp complex numbers because we told the
970 * translator to assume the return values of log and sqrt
971 * would not be complex, and it correctly returned the complex
972 * numbers returned by LOG and SQRT directly.
975 [every (?complexp, l2),
976 every ("#", l1, l2)]);
980 block ([tr_float_can_branch_complex : true],
981 translate_or_lose (foo),
982 /* l3 is a list of Maxima complex numbers because we told the
983 * translator to assume the return values of log and sqrt
984 * could be complex, and it converted the lisp complex numbers
985 * returned by LOG and SQRT to Maxima complex numbers.
988 every (lambda ([x, y], cabs (x - y) < 1e-15), l1, l3));
991 (kill (foo, x, l1, l2, l3), 0);
994 /* The translations for evaluating = and # expressions to boolean
995 * values with one float argument and a different numerical argument
996 * (e.g. a fixnum) gave bogus results because the translator was
997 * incorrectly applying float contagion to the arguments.
1000 (foo (s, w, x, y, z) :=
1001 (mode_declare (w, number, x, fixnum, y, flonum),
1002 [/* These translate to EQL comparisons */
1003 is (1 = 1), is (1 # 1),
1004 is (1 = 1.0), is (1 # 1.0),
1005 is (1 = float (1)), is (1 # float (1)),
1006 is (1.0 = float (1)), is (1.0 # float (1)),
1007 is (w = 2), is (w # 2),
1008 is (w = 2.0), is (w # 2.0),
1009 is (x = 3), is (x # 3),
1010 is (x = 3.0), is (x # 3.0),
1011 is (x = float (3)), is (x # float (3)),
1012 is (x = float (x)), is (x # float (x)),
1013 is (y = 4), is (y # 4),
1014 is (y = 4.0), is (y # 4.0),
1015 is (y = float (4)), is (y # float (4)),
1016 is (y = float (y)), is (y # float (y)),
1017 /* These translate to LIKE comparisons */
1018 is (z = 5), is (z # 5),
1019 is (z = 5.0), is (z # 5.0),
1020 is (z = float (5)), is (z # float (5)),
1021 is (z = float (z)), is (z # float (z)),
1022 is (1/2 = 1/2), is (1/2 # 1/2),
1023 is (1/2 = rat (1/2)), is (1/2 # rat (1/2)),
1024 is (rat (1/2) = rat (1/2)), is (rat (1/2) # rat (1/2)),
1025 is (1/2 = 0.5), is (1/2 # 0.5),
1026 is (1/2 = float (1/2)), is (1/2 # float (1/2)),
1027 is (%i = %i), is (%i # %i),
1028 is (1 + %i = 1 + %i), is (1 + %i # 1 + %i),
1029 is (s = s), is (s # s),
1030 is (s = 'bar), is (s # 'bar),
1031 is (s = 1), is (s # 1),
1032 is (s = 1.0), is (s # 1.0),
1033 is (s = 1/2), is (s # 1/2),
1034 is ('f (0) = 'f (0)), is ('f (0) # 'f (0)),
1035 is ('g (s) = 'g (s)), is ('g (s) # 'g (s)),
1036 is ('h (w) = 'h (w)), is ('h (w) # 'h (w)),
1037 is ('i (x) = 'i (x)), is ('i (x) # 'i (x)),
1038 is ('j (y) = 'j (y)), is ('j (y) # 'j (y)),
1039 is ('k (z) = 'k (z)), is ('k (z) # 'k (z))]),
1040 l1 : foo ('bar, 2, 3, 4.0, 5),
1041 translate_or_lose (foo),
1042 l2 : foo ('bar, 2, 3, 4.0, 5),
1043 [every (lambda ([x], ?typep (x, ?boolean)), l2),
1048 (kill (foo, w, x, y, l1, l2), 0);
1051 /* Bug #3048: notequal is not translated properly
1053 * notequal expressions were only generically translated like user
1054 * function calls and the use of notequal in translated code caused
1055 * a runtime warning about it being totally undefined. Also the
1056 * evaluation of notequal expressions to boolean values (via is, if,
1057 * etc.) were translated like the evaluation of an unknown predicate.
1060 (assume (equal (a, b), notequal (c, d)),
1063 is (notequal (1, 1)),
1064 is (equal (1, 1.0)),
1065 is (notequal (1, 1.0)),
1066 is (equal (1, 1.0b0)),
1067 is (notequal (1, 1.0b0)),
1068 is (equal (1/2, 0.5)),
1069 is (notequal (1/2, 0.5)),
1070 is (equal (1/2, 0.5b0)),
1071 is (notequal (1/2, 0.5b0)),
1073 is (notequal (1, 2)),
1074 is (equal ('ind, 'ind)),
1075 is (notequal ('ind, 'ind)),
1076 is (equal ('und, 'und)),
1077 is (notequal ('und, 'und)),
1078 is (equal ('a, 'b)),
1079 is (notequal ('a, 'b)),
1080 is (equal ('c, 'd)),
1081 is (notequal ('c, 'd)),
1082 is (equal (x^2 - 1, (x + 1) * (x - 1))),
1083 is (notequal (x^2 - 1, (x + 1) * (x - 1)))],
1085 translate_or_lose (foo),
1087 [every (lambda ([x], ?typep (x, ?boolean)), l2),
1092 (kill (foo, l1, l2),
1093 forget (equal (a, b), notequal (c, d)),
1097 /* The translation of a call to random with a float argument could
1098 * cause the generation of bogus code because this always had the
1102 (foo (w, x, y, z) :=
1103 (mode_declare (w, fixnum, x, float),
1112 1 / (1 + random (x))],
1116 1 / (1 + random (w)),
1117 1 / (1 + random (y))]]),
1118 translate_or_lose (foo),
1119 l : foo (50, 5.0, 100, 10.0),
1120 [every (integerp, first (l)),
1121 every (floatnump, second (l)),
1122 every (ratnump, third (l))]);
1127 (kill (foo, w, x, l), 0);
1130 /* acosh, asech, atanh and acoth now have special translations for
1131 * float arguments. These all honor tr_float_can_branch_complex.
1135 (mode_declare (x, float),
1136 [acosh (x), asech (x), atanh (x)]),
1138 (mode_declare (x, float),
1140 /* l1 is a list of Maxima complex numbers */
1141 l1 : append (foo (-3.0), foo (-2.0), bar (-0.5), bar (0.5)),
1142 some (lambda ([x], freeof (%i, x)), l1));
1145 block ([tr_float_can_branch_complex : false],
1146 translate_or_lose (foo, bar),
1147 /* l2 is a list of lisp complex numbers because we told the
1148 * translator to assume the return values would not be complex,
1149 * and it correctly returned the lisp complex numbers directly.
1151 l2 : append (foo (-3.0), foo (-2.0), bar (-0.5), bar (0.5)),
1152 [every (?complexp, l2),
1153 every ("#", l1, l2),
1154 every ("=", l1, map (?complexify, l2))]);
1159 block ([tr_float_can_branch_complex : true],
1160 translate_or_lose (foo, bar),
1161 /* l3 is a list of Maxima complex numbers because we told the
1162 * translator to assume the return values could be complex, and
1163 * it converted the lisp complex numbers to Maxima complex numbers.
1165 l3 : append (foo (-3.0), foo (-2.0), bar (-0.5), bar (0.5)),
1166 every ("=", l1, l3));
1169 (kill (foo, bar, x, l1, l2, l3), 0);
1172 /* Bug #3642: Lisp error when translating assume
1174 * Translating an assume call with an atomic argument would cause a
1175 * lisp error during translation.
1179 block ([ctx : supcontext (),
1183 assume (x, y, equal (c, 0)),
1184 r : [is (a > 0), is (b < 0), is (equal (c, 0))],
1187 translate_or_lose (foo),
1189 [true, false, true];
1194 /* The translation of errcatch was broken because the mode of the
1195 * whole form was always assumed to be the same as the mode of the
1196 * last subform. Since errcatch always yields a list, lisp errors
1197 * could easily occur.
1201 block ([listarith : true],
1204 1.0 * errcatch (2.0),
1205 errcatch (error ("oops")),
1206 errcatch (?error ("oops")),
1208 translate_or_lose (foo),
1220 /* Attempting to translate multiple functions containing local would
1221 * cause an error. Similarly, translating the same function multiple
1222 * times would cause an error if that function contained local.
1225 (foo () := local (), /* just something with local (not within a block) */
1226 bar () := local (), /* something else with local (not within a block) */
1227 translate_or_lose (foo),
1228 translate_or_lose (bar),
1229 translate_or_lose (foo, bar));
1232 (kill (foo, bar), 0);
1235 /* Bug #2976: "local" doesn't work in translated code
1237 * For decades no attempt was being made to clean up any local
1241 /* The internal LOCLIST used by local should be empty right now */
1250 translate_or_lose (foo1),
1251 block ([v : foo1 ()],
1255 (kill (f0, foo1), 0);
1258 (arr1 [0] : "three",
1260 block ([g : lambda ([],
1266 arrayinfo (arr2)])],
1268 translate_or_lose (foo2),
1269 block ([v : foo2 ()],
1272 errcatch (arrayinfo (arr2))]));
1279 (kill (arr1, foo2), 0);
1289 translate_or_lose (foo3),
1296 /* The internal LOCLIST used by local should be empty right now */
1300 /* The fpprintprec itself is not important in this test. I'm
1301 * just picking something that has an ASSIGN property because
1302 * that's a separate internal case in the translator.
1304 * This test is ugly, but it's testing different cases and
1305 * their interactions.
1308 local (f1, f2, arr),
1312 bar (fpprintprec) :=
1321 [f1 (), f2 (), arr [1]]),
1322 [f1 (), f2 (), arr [1]]]),
1323 translate_or_lose (bar),
1325 [is (?get ('fpprintprec, '?assign) = false),
1327 [f1 (), f2 (), arr [1]]]);
1336 /* This is testing to make sure there are no bad interactions
1337 * between the usual local cleanup and errcatch cleanup (this
1338 * also mixes the interpreted and translated cases). This test
1341 * The original implementation of local properties (from decades
1342 * ago) not only failed to clean up local properties at all, but
1343 * it wasn't even setting up the internal state to keep up with
1344 * these properties correctly. An initial attempt at fixing bug
1345 * #2976 made this problem clear because with that it was easy to
1346 * cause an infinite loop during certain things like errcatch
1349 block ([translate : false,
1361 translate_or_lose (baz1, baz2),
1374 translate_or_lose (baz_test),
1387 /* The internal LOCLIST used by local should be empty right now */
1391 (kill (baz1, baz2, baz_test), 0);
1394 /***** This ends the bug #2976 tests *****/
1396 /* compile wasn't always compiling the correct function
1398 * This test not only depends on the internal details of how certain
1399 * functions are currently translated, but it also depends on internal
1400 * details about how DEFMFUN defines functions. This also doesn't
1401 * really test that the correct function gets compiled because the
1402 * lisp implementation could have just compiled it itself anyway. Ugh.
1406 compile_or_lose (foo),
1407 ?compiled\-function\-p (?symbol\-function (?get (foo, ?impl\-name))));
1413 /* Some internal function definitions and compiler macros were not
1414 * being cleaned up, and this could cause confusing and bogus results
1415 * when an outdated compiler macro was being used.
1417 * Specifically one problem we had involved translating a function,
1418 * redefining it and then translating the new definition. The internal
1419 * function and compiler macro from the original function could be used
1420 * when compiling calls to the new function if they were not overwritten.
1422 * This all depended on lisp implementation-dependent behavior because
1423 * implementations are not required to ever use compiler macros. Ugh.
1425 * This test also depends on internal details of how certain functions
1426 * are currently translated. Double ugh.
1430 translate_or_lose (foo),
1433 translate_or_lose (foo),
1435 test2 () := foo (1, 2, 3),
1436 compile_or_lose (test1, test2),
1437 /* Previously we observed test1 returning 0 and test2 causing a lisp
1438 * error because the compiler macro and old internal function from
1439 * the first foo were being used.
1441 [test1 (), test2 ()]);
1444 (kill (foo, test1, test2), 0);
1447 /* https://stackoverflow.com/questions/64631208/compilation-global-variables-with-warning
1449 * First verify that error_syms and niceindicespref assignments work as expected.
1455 errcatch (error_syms: 123);
1458 errcatch (error_syms: [aa, bb, 123]);
1461 error_syms: [aa, bb, cc];
1464 errcatch (niceindicespref: 123);
1467 errcatch (niceindicespref: []);
1470 niceindicespref: [aa, bb, cc];
1473 (reset (error_syms, niceindicespref), 0);
1476 /* now the example from the Stackoverflow question */
1479 "define_variable(foo, true, boolean)$
1482 exprp(that) := if foo = false and listp(that) and not emptyp(that) and member(that[1], [\"+\", \"*\"]) then(foo: true, true)$
1483 matchdeclare(exprm, exprp)$
1484 defrule(rule_1, exprm, subst(exprm[1], \"[\", exprm[2]))$
1486 calc(list) := block([steps: []],
1488 steps: endcons(list, steps),
1490 list: applyb1(list, rule_1)
1495 calc_result: calc([\"+\", [[\"*\", [1, 2, 3]], [\"+\", [3, 4, 6]]]]);",
1496 program_file_name: sconcat (maxima_tempdir, "/tmp_program.mac"),
1497 with_stdout (program_file_name, print (program_content)),
1504 ([file_name_original, file_name_LISP, file_name_UNLISP, file_name_compiled]: compile_file (program_file_name), 0);
1507 stringp (file_name_compiled);
1513 (load (file_name_compiled),
1515 [["+", [["*", [1, 2, 3]], ["+", [3, 4, 6]]]],
1516 ["+", [6, ["+", [3, 4, 6]]]],
1520 (kill (program_content, program_file_name, file_name_original, file_name_LISP, file_name_UNLISP, file_name_compiled, calc_result), 0);
1524 /* Some additional basic tests for functions with rest args */
1526 block ([translate : false],
1528 bar (a, b, [c]) := [a, b, c],
1537 bar (1, 2, 3, 4, 5)],
1539 /* l1: foo, bar and test are interpreted */
1542 /* l2: foo and bar are translated, and test is interpreted */
1543 translate_or_lose (foo, bar),
1546 /* l3: foo, bar and test are translated */
1547 translate_or_lose (test),
1562 [1, 2, [3, 4, 5]]]];
1564 (kill (foo, bar, test, l1, l2, l3), 0);
1567 /* Attempting to translate a macro with a rest arg always caused an
1568 * error during translation because the translator was constructing
1569 * bogus Maclisp-style lexpr lambda expressions.
1572 block ([translate : false],
1574 buildq ([r], ['r, r]),
1576 buildq ([a, b, c], ['a, a, 'b, b, 'c, c]),
1578 block ([x : 1, z : 3],
1584 bar (x, y, z, 4, 5, 6)]),
1585 /* test2 cannot be translated due to the WNA error during macro
1586 * expansion, but we can call and test it in the interpreter
1590 errcatch (bar (1))],
1592 /* l1: foo, bar and test1 are interpreted */
1595 /* l2: foo and bar are translated, and test1 is interpreted */
1596 translate_or_lose (foo, bar),
1599 /* l3: foo, bar and test1 are translated */
1600 translate_or_lose (test1),
1612 [['x, 'y, 'z], [1, 'y, 3]],
1613 ['x, 1, 'y, 'y, [], []],
1614 ['x, 1, 'y, 'y, ['z], [3]],
1615 ['x, 1, 'y, 'y, ['z, 4, 5, 6], [3, 4, 5, 6]]]];
1617 (kill (foo, bar, test1, test2, l1, l2, l3), 0);
1620 /* Some additional basic tests for conditionals.
1622 * We test both elseif and else-if ("else if").
1625 block ([translate : false],
1626 mysignum1 (x) := if x > 0 then 1 elseif x < 0 then -1 else 0,
1627 mysignum2 (x) := if x > 0 then 1 else if x < 0 then -1 else 0,
1631 if true then 1 else 2,
1632 if false then 1 else 2,
1634 if 1 < 2 then 'y else 'n,
1636 if 1 > 2 then 'n else 'y,
1637 if 1 > 2 then 'n elseif 1 = 2 then 'n else 'y,
1638 if 1 > 2 then 'n else if 1 = 2 then 'n else 'y,
1646 translate_or_lose (mysignum1, mysignum2, foo),
1651 [1, false, 1, 2, 'y, 'y, false, 'y, 'y, 'y, -1, -1, 0, 0, 1, 1]];
1653 (kill (mysignum1, mysignum2, foo, l1, l2), 0);
1656 /* Bogus translations of nested conditionals in elseif clauses
1658 * The translation of a conditional with another conditional nested
1659 * directly under an elseif clause was totally wrong. Using else-if
1660 * ("else if") instead of elseif would work fine.
1663 * We use the with_both_elseifs macro so we can test both elseif and
1664 * else-if without having to duplicate portions of the tests below.
1665 * Give this macro a conditional expression with elseifs and it will
1666 * expand into a list: the first element is the same expression given
1667 * to it (with elseifs), and the second element is that same expression
1668 * rewritten to use else-ifs instead of elseifs.
1671 (to_else_if (expr) :=
1672 if mapatom (expr) then
1675 block ([op : op (expr), args : args (expr)],
1676 if op = "if" and length (args) > 4 then
1677 funmake (op, map ('to_else_if, append (firstn (args, 2), [true, funmake (op, rest (args, 2))])))
1679 funmake (op, map ('to_else_if, args))),
1680 with_both_elseifs (expr) ::=
1681 buildq ([expr, texpr : to_else_if (expr)],
1686 block ([translate : false],
1701 /* l1: foo is interpreted */
1704 translate_or_lose (foo),
1706 /* l2: foo is translated
1708 * foo used to give lose3 instead of win in the elseif case.
1717 block ([translate : false],
1718 /* There is nothing special about bar here. This is just some
1719 * function that has several branches with nested conditionals.
1747 /* We test bar with the integers -2 to 9 */
1748 inputs : makelist (k, k, -2, 9),
1750 /* l1: bar is interpreted */
1751 l1 : map (bar, inputs),
1753 translate_or_lose (bar),
1755 /* l2: bar is translated
1757 * bar used to give incorrect results in the elseif case for every
1758 * number less than or equal to 2 (which means we got incorrect
1759 * results for the integers -2 to 2 in this test).
1761 l2 : map (bar, inputs),
1766 [['negative, 'negative],
1767 ['negative, 'negative],
1776 ['more_than_seven, 'more_than_seven],
1777 ['more_than_seven, 'more_than_seven]]];
1779 (kill (foo, bar, l1, l2, inputs, to_else_if, with_both_elseifs), 0);
1782 /* Bogus translations of conditionals with tests that translated to T
1783 * and consequents that translated to NIL.
1786 block ([translate : false],
1788 [if true then false else 1,
1789 if true then false elseif true then 1 else 2,
1790 if false then true elseif true then false else 1],
1792 /* l1: foo is interpreted */
1795 translate_or_lose (foo),
1797 /* l2: foo is translated
1799 * foo used to return [1, 1, 1]
1806 [false, false, false]];
1808 (kill (foo, l1, l2), 0);
1811 /* Bug #3704: Translator gives internal error
1813 * The hyper_to_summand function is from the bug report.
1816 (hyper_to_summand(e,k) := subst(hypergeometric = lambda([P,Q,x],
1817 P : xreduce("*", map(lambda([zz], pochhammer(zz,k)),P)),
1818 Q : xreduce("*", map(lambda([zz], pochhammer(zz,k)),Q)),
1820 l1 : hyper_to_summand (hypergeometric ([1/2], [2/5], x), 2),
1821 translate_or_lose (hyper_to_summand),
1822 l2 : hyper_to_summand (hypergeometric ([1/2], [2/5], x), 2),
1823 [is (l1 = l2), l2]);
1824 [true, 75 * x^2 / 112];
1826 (foo () := lambda ([], x!),
1827 translate_or_lose (foo),
1828 block ([x : 5], foo () ()));
1831 (kill (hyper_to_summand, foo, l1, l2), 0);
1834 /* go tags can be integers
1836 * This has been allowed, but it used to give a warning and an extra
1837 * trivial run through the translator to translate the integer go tags.
1838 * Now we allow integers directly without giving a warning.
1840 * We don't actually bother to check for warnings in the test below.
1841 * We're really just verifying that using an integer go tag works.
1844 block ([translate : false],
1845 foo () := block ([i : 0], tag, i : i + 1, if i < 5 then go (tag), i),
1846 bar () := block ([i : 0], 123, i : i + 1, if i < 5 then go (123), i),
1847 l1 : [foo (), bar ()],
1848 translate_or_lose (foo, bar),
1849 l2 : [foo (), bar ()],
1850 [is (l1 = l2), l2]);
1853 (kill (foo, bar, l1, l2), 0);
1856 /* A bug in MARRAYREF caused things like translated array references
1857 * to yield MQAPPLY expressions with an incorrect header.
1860 block ([translate : false],
1861 foo () := 'baz () [1],
1862 bar () := 'baz () [1, 2, 3],
1863 l1 : [foo (), bar ()],
1864 translate_or_lose (foo, bar),
1865 l2 : [foo (), bar ()],
1866 [is (l1 = l2), l2]);
1867 [true, ['baz () [1], 'baz () [1, 2, 3]]];
1869 (kill (foo, bar, l1, l2), 0);
1872 /* A bug in MARRAYREF caused bogus indexing into hash tables and fast
1873 * arrays. This affected things like translated array references.
1876 block ([translate : false,
1877 use_fast_arrays : true],
1879 foo () := block ([a],
1884 /* This would correctly yield 2 */
1887 translate_or_lose (foo),
1889 /* This used to incorrectly yield wtf */
1892 [is (l1 = l2), l2]);
1895 (kill (foo, l1, l2), 0);
1898 /* A bug in MARRAYREF caused things like translated array references
1899 * to yield expressions with an incorrect header.
1902 block ([translate : false],
1903 foo () := block ([a],
1905 array (a, complete, 5),
1908 /* This would correctly yield a[3] */
1911 translate_or_lose (foo),
1913 /* This would incorrectly yield a(3) */
1916 [is (l1 = l2), l2]);
1919 (kill (foo, l1, l2), 0);
1922 /* When translate_fast_arrays:true, a lisp error would occur at runtime
1923 * during an attempted MQAPPLY array assignment
1926 block ([translate : false],
1927 foo () := block ([a],
1929 a : make_array ('fixnum, 5),
1934 /* This would correctly yield 17 */
1937 block ([translate_fast_arrays : false],
1938 translate_or_lose (foo)),
1940 /* This would correctly yield 17 */
1943 block ([translate_fast_arrays : true],
1944 translate_or_lose (foo)),
1946 /* This would cause a lisp error */
1949 [is (l1 = l2), is (l2 = l3), l3]);
1952 (kill (foo, l1, l2, l3), 0);
1955 /* The string "**" no longer translates to the string "^".
1956 * This test compares the interpreted and translated results.
1959 block ([translate : false],
1960 foo () := ["^", "^" (2, 3), apply ("^", [2, 3]),
1961 "**", "**" (2, 3), apply ("**", [2, 3])],
1963 translate_or_lose (foo),
1965 [l2, is (l1 = l2)]);
1966 [["^", 8, 8, "**", 8, 8], true];
1968 (kill (foo, l1, l2), 0);
1971 /* Attempting to translate some atoms like lisp arrays would
1972 * cause lisp errors during translation.
1975 (a : make_array (fixnum, 1),
1978 translate_or_lose (foo),
1979 listarray (foo ()));
1985 /* Simple tests for catch and throw */
1987 block ([translate : false, l1, l2],
1988 local (foo, bar, baz),
1990 foo (p) := if p then throw (13) else 2,
1991 bar () := catch (1, foo (false), 3),
1992 baz () := catch (1, foo (true), 3),
1994 l1 : [bar (), baz ()],
1996 translate_or_lose (foo, bar, baz),
1998 l2 : [bar (), baz ()],
2000 [l2, is (l1 = l2)]);
2003 block ([translate : false, l1, l2],
2006 foo (p) := throw (if p then 1/2 else 'other),
2007 bar (p) := 1 + catch (foo (p), 2),
2009 l1 : [bar (true), bar (false)],
2011 translate_or_lose (foo, bar),
2013 l2 : [bar (true), bar (false)],
2015 [l2, is (l1 = l2)]);
2016 [[3/2, 1 + 'other], true];
2018 (kill (foo, bar), 0);
2021 /* Translating a define_variable form with translate (but not
2022 * translate_file or compfile) used to invoke undefined behavior.
2023 * This would cause a lisp error during translation under some
2024 * (but not all) lisp implementations.
2027 block ([translate : false],
2029 foo () := (define_variable (x, 1, fixnum), x),
2030 translate_or_lose (foo),
2037 /* If local was used on a matchdeclared pattern variable, and this
2038 * was all translated with something besides translate_file (e.g.,
2039 * translate, compfile, etc.), then the MATCHDECLARE property would
2040 * not be on the pattern variable.
2043 block ([translate : false, l1, l2],
2046 foo () := (local (x), matchdeclare (x, true), let (a * x, x), letsimp (a * q)),
2048 /* This would yield q */
2051 translate_or_lose (foo),
2053 /* This used to yield a*q */
2056 [l2, is (l1 = l2)]);
2062 /* Rest args are now allowed in lambda expressions in MQAPPLY
2066 block ([translate : false, l1, l2],
2067 local (foo, bar, baz),
2069 /* foo used to fail to translate due to the rest arg */
2071 block ([x : 1, z : 3],
2072 lambda ([[x]], x) (x, x + 1, z)),
2074 block ([x : 2, z : 4],
2075 apply (lambda ([[x]], x), [x, x + 1, z])),
2077 block ([x : 3, z : 5],
2078 block ([f : lambda ([[x]], x)],
2081 l1 : [foo (), bar (), baz ()],
2083 translate_or_lose (foo, bar, baz),
2085 l2 : [foo (), bar (), baz ()],
2087 [l1, is (l1 = l2)]);
2088 [[[1, 2, 3],[2, 3, 4],[3, 4, 5]], true];
2090 /* Validation has been improved for lambda expressions in MQAPPLY
2094 block ([translate : false],
2097 /* These should both fail to translate */
2098 foo () := lambda ([]) (),
2099 bar () := lambda ([x, x], x) (1, 2),
2101 translate (foo, bar));
2104 /* The translation of array functions was broken for decades */
2106 block ([translate : false, l1, l2],
2110 bar[n] := if n = 1 then 1 else n * bar[n - 1],
2112 l1 : [foo[0], foo[5], bar[5], bar[10]],
2114 translate_or_lose (foo, bar),
2116 l2 : [foo[0], foo[5], bar[5], bar[10]],
2118 [l1, is (l1 = l2)]);
2119 [[0, 5, 120, 3628800], true];
2121 (kill (foo, bar), 0);
2124 /* The translation of upward funargs (including those created by
2125 * subscripted functions) easily lead to lisp errors.
2128 /* Tests involving returned lambdas without free vars that were
2129 * bound during definition
2134 local (foo, bar, test),
2136 foo () := lambda ([x], 2 * x + q),
2137 bar () := lambda ([x, [y]], x * y + q),
2142 [f (3), f (5), b (2, 3, 4), b (5, 6, 7)]),
2146 translate_or_lose (foo, bar),
2150 [l2, is (l1 = l2)]);
2151 [['q + 6, 'q + 10, ['q + 6, 'q + 8], ['q + 30, 'q + 35]],
2154 (kill (foo, bar), 0);
2157 /* Tests involving returned lambdas with free vars that were
2158 * bound during definition. These do not cause the capture of
2165 local (foo, bar, baz, test),
2167 foo (x) := lambda ([y], x + y + q),
2168 bar (x) := lambda ([y, [z]], q + x + y * z),
2169 baz (v) := lambda ([], v),
2172 block ([f : foo (3),
2175 [f (5), b (2, 3, 4), c ()]),
2179 translate_or_lose (foo, bar, baz),
2183 [l2, is (l1 = l2)]);
2185 ['q + 'ux + 6, 'q + 'ux + 8],
2189 (kill (foo, bar, baz), 0);
2192 /* Tests involving subscripted functions. These do cause the capture
2198 local (foo, bar, baz, def, test),
2201 foo[x, y](a, b) := [x, y, a, b, q],
2202 bar[x, y](a, [b]) := [x, y, a, b, q],
2206 block ([f : foo[1, 2],
2209 [f (6, 7), b (8, 9, 10), c ()]),
2215 /* just kill and redefine */
2217 kill (foo, bar, baz),
2221 translate_or_lose (foo, bar, baz),
2225 [l2, is (l1 = l2)]);
2227 [3, 4, 8, [9, 10], 'q],
2231 (kill (foo, bar, baz), 0);
2234 /* More tests involving multiple nested lambdas */
2236 x : 'ux, y : 'uy, z : 'uz,
2238 local (foo, bar, baz, quux, def, test),
2241 /* nothing should be captured */
2242 foo (x) := lambda ([y], lambda ([z], [x, y, z])),
2243 /* x should be captured and used */
2244 bar[x](y) := lambda ([z], [x, y, z]),
2245 /* x should be captured and used */
2246 baz[x](y) := lambda ([z], lambda ([], [x, y, z])),
2247 /* nothing should be captured since x is bound by the inner lambda */
2248 quux[x](y) := lambda ([x], [x, y])),
2251 block ([a : foo (1),
2255 [a (10) (11), b (12) (13), c (14) (15) (), d (16) (17)]),
2261 /* just kill and redefine */
2263 kill (foo, bar, baz, quux),
2267 translate_or_lose (foo, bar, baz, quux),
2271 [l2, is (l1 = l2)]);
2278 (kill (foo, bar, baz, quux), 0);
2281 /* The translator was not correctly determining the mode of expressions
2282 * when a boolean mode was involved.
2284 * It was easy to get lisp errors.
2286 block ([translate : false, l1, l2],
2290 [ 1 + if true then 0,
2291 1 + if true then 0.0,
2292 1.0 + if true then 0,
2293 1.0 + if true then 0.0,
2295 1 + if false then 0,
2296 1 + if false then 0.0,
2297 1.0 + if false then 0,
2298 1.0 + if false then 0.0],
2304 1.0 + if x then 0.0],
2308 for prederror in [true, false] do
2310 for x in [true, false] do
2311 push (bar (x), res),
2316 translate_or_lose (foo, bar),
2323 (kill (foo, bar), 0);
2327 * Bug #4008: translator and prederror
2330 (kill (pred, foo, bar, x, r), 0);
2333 block ([translate : false, l1, l2],
2337 [if true then q + r,
2338 if false then q + r,
2342 if not not x then q,
2343 if not not not x then q,
2345 n + if x then q + r,
2346 n + if not x then q + r,
2347 n + if not not x then q + r,
2348 n + if not not not x then q + r],
2352 for prederror in [true, false] do
2353 for n in [1, 1.0, %i, 1.0 * %i] do
2354 for q in [1, 1.0, %i, 1.0 * %i, 'z] do
2355 for x in [true, false] do
2356 push (foo (n, q, x), res),
2361 translate_or_lose (foo),
2371 block ([translate : false, l1, l2],
2376 [if "and" () then q else r,
2377 if "and" (x) then q else r,
2378 if "and" (y) then q else r,
2379 if x and y then q else r,
2380 if not x and y then q else r,
2381 if x and not y then q else r,
2382 if not x and not y then q else r,
2383 if not (x and y) then q else r,
2384 if not (not x and y) then q else r,
2385 if not (x and not y) then q else r,
2386 if not (not x and not y) then q else r,
2388 if "or" () then q else r,
2389 if "or" (x) then q else r,
2390 if "or" (y) then q else r,
2391 if x or y then q else r,
2392 if not x or y then q else r,
2393 if x or not y then q else r,
2394 if not x or not y then q else r,
2395 if not (x or y) then q else r,
2396 if not (not x or y) then q else r,
2397 if not (x or not y) then q else r,
2398 if not (not x or not y) then q else r]),
2402 for prederror in [true, false] do
2403 for x in [true, false] do
2404 for y in [true, false] do
2405 push (foo (x, y), res),
2410 translate_or_lose (foo),
2420 block ([translate : false, l1, l2],
2421 local (test, make_fun),
2423 make_fun (name, pr) ::=
2433 pr (not x and not y),
2435 pr (not (not x and y)),
2436 pr (not (x and not y)),
2437 pr (not (not x and not y)),
2445 pr (not x or not y),
2447 pr (not (not x or y)),
2448 pr (not (x or not y)),
2449 pr (not (not x or not y))])),
2452 make_fun (bar, maybe),
2456 for prederror in [true, false] do
2457 for x in [true, false] do
2458 for y in [true, false] do (
2459 push (foo (x, y), res),
2460 push (bar (x, y), res)),
2465 translate_or_lose (foo, bar),
2472 (kill (foo, bar), 0);
2475 block ([translate : false, l1, l2],
2478 pred (a, b) := equal (a, b),
2482 [if x < y then q else r,
2483 if not (x < y) then q else r,
2484 if x <= y then q else r,
2485 if not (x <= y) then q else r,
2486 if x > y then q else r,
2487 if not (x > y) then q else r,
2488 if x >= y then q else r,
2489 if not (x >= y) then q else r,
2491 if x = y then q else r,
2492 if x # y then q else r,
2493 if not (x = y) then q else r,
2494 if not (x # y) then q else r,
2495 if not not (x = y) then q else r,
2496 if not not (x # y) then q else r,
2497 if not not not (x = y) then q else r,
2498 if not not not (x # y) then q else r,
2500 if equal (x, y) then q else r,
2501 if notequal (x, y) then q else r,
2502 if not equal (x, y) then q else r,
2503 if not not equal (x, y) then q else r,
2504 if not notequal (x, y) then q else r,
2505 if not not not equal (x, y) then q else r,
2506 if not not notequal (x, y) then q else r,
2508 if pred (x, y) then q else r,
2509 if not pred (x, y) then q else r,
2510 if not not pred (x, y) then q else r,
2511 if not not not pred (x, y) then q else r]),
2515 for prederror in [true, false] do
2518 push (foo (x, y), res),
2523 translate_or_lose (pred, foo),
2530 (kill (pred, foo), 0);
2533 block ([translate : false, l1, l2],
2534 local (test, make_fun),
2536 pred (a, b) := equal (a, b),
2538 make_fun (name, pr) ::=
2546 pr (not not (x = y)),
2547 pr (not not (x # y)),
2548 pr (not not not (x = y)),
2549 pr (not not not (x # y)),
2552 pr (not equal (x, y)),
2553 pr (notequal (x, y)),
2554 pr (not not equal (x, y)),
2555 pr (not notequal (x, y)),
2556 pr (not not not equal (x, y)),
2557 pr (not not notequal (x, y)),
2560 pr (not pred (x, y)),
2561 pr (not not pred (x, y)),
2562 pr (not not not pred (x, y))])),
2565 make_fun (bar, maybe),
2569 for prederror in [true, false] do
2571 for y in [1, 2] do (
2572 push (foo (x, y), res),
2573 push (bar (x, y), res)),
2578 translate_or_lose (pred, foo, bar),
2585 (kill (pred, foo, bar), 0);
2588 block ([translate : false, l1, l2],
2592 [if (1, 2, q, x) then q else r,
2593 if not (1, 2, q, x) then q else r,
2594 if (1, 2, q, not x) then q else r],
2598 for prederror in [true, false] do
2599 for x in [true, false] do
2600 push (foo (x, 17), res),
2605 translate_or_lose (foo),
2615 block ([translate : false, l1, l2],
2616 local (test, make_fun),
2618 make_fun (name, pr) ::=
2635 pr (not not (x and y)),
2636 pr (not not (x or y)),
2637 pr (not not not (x and y)),
2638 pr (not not not (x or y)),
2642 pr (x and not not y),
2643 pr (x or not not y),
2644 pr (not (x and not y)),
2645 pr (not (x or not y)),
2646 pr (not (x and not not y)),
2647 pr (not (x or not not y)),
2651 pr (not not x and y),
2652 pr (not not x or y),
2653 pr (not (not x and y)),
2654 pr (not (not x or y)),
2655 pr (not (not not x and y)),
2656 pr (not (not not x or y)),
2658 pr (not x and not y),
2659 pr (not x or not y),
2660 pr (not (not x and not y)),
2661 pr (not (not x or not y)),
2667 pr (x > 1 and not y),
2668 pr (x > 1 or not y),
2669 pr (not x > 1 and y),
2670 pr (not x > 1 or y),
2671 pr (not x > 1 and not y),
2672 pr (not x > 1 or not y),
2678 pr (x and not y <= 1),
2679 pr (x or not y <= 1),
2680 pr (not x and y <= 1),
2681 pr (not x or y <= 1),
2682 pr (not x and not y <= 1),
2683 pr (not x or not y <= 1)]),
2686 make_fun (bar, maybe),
2689 block ([prederror : false,
2690 l : [true, false, 1, 2.0, 'q, 'q ()],
2694 push (foo (x, y), res),
2695 push (bar (x, y), res)),
2700 translate_or_lose (foo, bar),
2707 (kill (foo, bar), 0);
2710 block ([translate : false, l1, l2],
2711 local (test, make_fun),
2713 make_fun (name, pr) ::=
2726 pr (not not (x < 1)),
2727 pr (not not (x <= 1)),
2728 pr (not not (x > 1)),
2729 pr (not not (x >= 1)),
2735 pr (not not (x = 1)),
2736 pr (not not (x # 1)),
2739 pr (notequal (x, 1)),
2740 pr (not equal (x, 1)),
2741 pr (not notequal (x, 1)),
2742 pr (not not equal (x, 1)),
2743 pr (not not notequal (x, 1))]),
2746 make_fun (bar, maybe),
2750 block ([prederror : true],
2751 push (errcatch (foo ('z)), res)),
2752 block ([prederror : false,
2756 %i, 1.0 * %i, 1.0b0 * %i,
2757 2 * %i, 2.0 * %i, 2.0b0 * %i,
2761 push (foo (x), res),
2762 push (bar (x), res))),
2767 translate_or_lose (foo, bar),
2774 (kill (foo, bar), 0);
2777 block ([translate : false, l1, l2],
2780 foo (x, q, prederror) :=
2784 if not not x then 0,
2785 if not not not x then 0,
2787 if not x then q + r,
2788 if not not x then q + r,
2789 if not not not x then q + r,
2791 if not x then 1 else 2,
2792 if not not x then 1 else 2,
2793 if not not not x then 1 else 2,
2794 if x then x else q + r,
2795 if not x then x else q + r,
2796 if not not x then x else q + r,
2797 if not not not x then x else q + r,
2798 if x = 1 then x else q + r,
2799 if x # 1 then x else q + r,
2800 if not x = 1 then x else q + r,
2801 if not x # 1 then x else q + r,
2802 if not not x = 1 then x else q + r,
2803 if not not x # 1 then x else q + r,
2804 if not not not x = 1 then x else q + r,
2805 if not not not x # 1 then x else q + r]),
2808 block ([l : [true, false, 1, 2.0, 3.0b0, 'z, 'z ()],
2810 push (errcatch (foo (1, 2, true)), res),
2813 push (foo (x, q, false), res),
2818 translate_or_lose (foo),
2828 block ([translate : false, l1, l2],
2829 local (rewritehack, eqhack, test),
2831 /* Take a relational expr and potentially rewrite it in some
2832 * equivalent way, e.g. x<1 => 1-x>0
2835 eval_string_lisp ("(apply #'mevalp2 $r (mop $r) (margs $r))")[1],
2837 /* Translated code can produce relational exprs that are in a
2838 * different, but equivalent, form compared to the exprs produce
2839 * by interpreted code.
2841 * Compare two conditionals by requiring that everything matches
2842 * exactly, except possibly the first (only) test. The tests
2843 * should match exactly after applying rewritehack to them.
2845 eqhack (interp, transl) :=
2846 if atom (interp) or atom (transl) or op (interp) # "if" or op (transl) # "if" then
2847 is (interp = transl)
2849 is (rest (interp) = rest (transl)
2851 rewritehack (first (interp)) = rewritehack (first (transl))),
2855 [if x < 1 then x else r,
2856 if x <= 1 then x else r,
2857 if x > 1 then x else r,
2858 if x >= 1 then x else r,
2860 if not (x < 1) then x else r,
2861 if not (x <= 1) then x else r,
2862 if not (x > 1) then x else r,
2863 if not (x >= 1) then x else r,
2865 if not not (x < 1) then x else r,
2866 if not not (x <= 1) then x else r,
2867 if not not (x > 1) then x else r,
2868 if not not (x >= 1) then x else r,
2870 if x = 1 then x else r,
2871 if x # 1 then x else r,
2872 if not (x = 1) then x else r,
2873 if not (x # 1) then x else r,
2874 if not not (x = 1) then x else r,
2875 if not not (x # 1) then x else r,
2877 if equal (x, 1) then x else r,
2878 if notequal (x, 1) then x else r,
2879 if not equal (x, 1) then x else r,
2880 if not notequal (x, 1) then x else r,
2881 if not not equal (x, 1) then x else r,
2882 if not not notequal (x, 1) then x else r]),
2886 block ([prederror : true],
2887 push (errcatch (foo ('z)), res)),
2888 block ([prederror : false,
2892 %i, 1.0 * %i, 1.0b0 * %i,
2893 2 * %i, 2.0 * %i, 2.0b0 * %i,
2897 res : append (foo (x), res)),
2902 translate_or_lose (foo),
2906 every (eqhack, l1, l2));
2912 block ([translate : false, l1, l2],
2917 [if x > 0 and y > 0 and z > 0 then x + y = z else r,
2918 if x > 0 or y > 0 or z > 0 then x + y = z else r,
2919 if x >= 1 and y >= 1 and z >= 1 then x + y = z else r,
2920 if x >= 1 or y >= 1 or z >= 1 then x + y = z else r,
2921 if x <= 2 and y <= 2 and z <= 2 then x + y = z else r,
2922 if x <= 2 or y <= 2 or z <= 2 then x + y = z else r,
2923 if x < 3 and y < 3 and z < 3 then x + y = z else r,
2924 if x < 3 or y < 3 or z < 3 then x + y = z else r]),
2927 block ([l : [1, 2.0, 3.0b0, %i],
2932 push (foo (x, y, z), res),
2937 translate_or_lose (foo),
2947 block ([translate : false, l1, l2],
2951 (modedeclare (p, boolean, x, fixnum, y, flonum, z, number),
2953 [if p and x > 0 and y > 0 and z > 0 then x + y - z else r,
2954 if p or x > 0 or y > 0 or z > 0 then x + y - z else r,
2955 if p and x >= 1 and y >= 1 and z >= 1 then x + y - z else r,
2956 if p or x >= 1 or y >= 1 or z >= 1 then x + y - z else r,
2957 if p and x <= 2 and y <= 2 and z <= 2 then x + y - z else r,
2958 if p or x <= 2 or y <= 2 or z <= 2 then x + y - z else r,
2959 if p and x < 3 and y < 3 and z < 3 then x + y - z else r,
2960 if p or x < 3 or y < 3 or z < 3 then x + y - z else r,
2962 if p and x > y and y > z and z > 3 then x + y + z else r,
2963 if p or x > y or y > z or z > 3 then x + y + z else r,
2964 if p and x >= y and y >= z and z >= 2 then x + y + z else r,
2965 if p or x >= y or y >= z or z >= 2 then x + y + z else r,
2966 if p and x <= y and y <= z and z <= 1 then x + y + z else r,
2967 if p or x <= y or y <= z or z <= 1 then x + y + z else r,
2968 if p and x < y and y < z and z < 0 then x + y + z else r,
2969 if p or x < y or y < z or z < 0 then x + y + z else r])),
2972 block ([bool : [true, false],
2973 fixl : [0, 1, 2, 3, 4],
2974 flol : [0.0, 1.0, 2.0, 3.0, 4.0],
2975 numl : [0, 1.0, 2, 3.0, 4],
2981 push (foo (p, x, y, z), res),
2986 translate_or_lose (foo),
2993 (kill (foo, p, x, y, z), 0);
2996 block ([translate : false, l1, l2],
3001 [if p and x and y and z then x + y = z else r,
3002 if p or x or y or z then x + y = z else r,
3004 if p and equal (x, 1) and equal (y, 1) and equal (z, 1) then x + y = z else r,
3005 if p or equal (x, 1) or equal (y, 1) or equal (z, 1) then x + y = z else r,
3007 if not p and not equal (x, 1) and not equal (y, 1) and not equal (z, 1) then x + y = z else r,
3008 if not p or not equal (x, 1) or not equal (y, 1) or not equal (z, 1) then x + y = z else r,
3010 if p and notequal (x, 1) and notequal (y, 1) and notequal (z, 1) then x + y = z else r,
3011 if p or notequal (x, 1) or notequal (y, 1) or notequal (z, 1) then x + y = z else r,
3013 if not p and not notequal (x, 1) and not notequal (y, 1) and not notequal (z, 1) then x + y = z else r,
3014 if not p or not notequal (x, 1) or not notequal (y, 1) or not notequal (z, 1) then x + y = z else r]),
3017 block ([prederror : false,
3018 l : [true, false, 1, 2.0, 3.0b0, %i, 'z, 'z ()],
3020 for p in [true, false] do
3024 push (foo (p, x, y, z), res),
3029 translate_or_lose (foo),
3039 block ([translate : false, l1, l2],
3042 pred (a, b) := equal (a, b),
3045 block ([r, var1, var2, v1 : 'var1, v2 : 'var2],
3046 [if pred (x, 1) then x,
3047 if not pred (x, 1) then x,
3048 if pred (x, 1) or pred (x, 2) then x,
3049 if pred (x, 1) then x else q + r,
3050 if not pred (x, 1) then x else q + r,
3051 if pred (x, 1) or pred (x, 2) then x else q + r,
3052 if pred (x, 1) then f (x + q) elseif pred (x, 2) then g (x + q) elseif pred (x, q) then v1 :: r * x else var1 : q * r,
3053 if pred (x, 1) then f (x + q) else if pred (x, 2) then g (x + q) else if pred (x, q) then v2 :: r * x else var2 : q * r,
3054 if pred (x, 1) and q then f (x + q) elseif pred (x, 2) or q then g (x + q) elseif not pred (x, q) then v1 :: r * x else var1 : q * r,
3055 if pred (x, 1) and q then f (x + q) else if pred (x, 2) or q then g (x + q) else if not pred (x, q) then v2 :: r * x else var2 : q * r,
3056 if pred (x, 1) and not q then f (x + q) elseif pred (x, 2) or not q then g (x + q) elseif not pred (x, q) then v1 :: r * x else var1 : q * r,
3057 if pred (x, 1) and not q then f (x + q) else if pred (x, 2) or not q then g (x + q) else if not pred (x, q) then v2 :: r * x else var2 : q * r]),
3061 block ([prederror : false],
3062 push (errcatch (foo (true, false)), res)),
3063 block ([prederror : false,
3064 l : [true, false, 1, 2.0, 3.0b0, %i, 'z, 'z ()]],
3067 push (foo (x, q), res)),
3072 translate_or_lose (pred, foo),
3079 (kill (pred, foo), 0);
3082 block ([translate : false, l1, l2],
3085 /* I really want push(x,a) below in foo, bar and baz,
3086 * but the translation of the push special form just
3087 * punts to MEVAL. I want the loop bodies translated
3088 * better than that, especially in baz, so just do
3089 * a:cons(x,a) everywhere here.
3094 for x : 1 thru 5 do a : cons (x, a),
3097 for x : 1 thru 5 while x < 3 do a : cons (x, a),
3100 for x : 1 thru 5 while x > 3 do a : cons (x, a),
3103 for x : 1 thru 5 while x < 10 do a : cons (x, a),
3106 for x : 1 thru 5 while x > 10 do a : cons (x, a),
3109 for x : 1 thru 5 unless x < 3 do a : cons (x, a),
3112 for x : 1 thru 5 unless x > 3 do a : cons (x, a),
3117 for x : 1 thru 5 while p do a : cons (x, a),
3120 for x : 1 thru 5 while x < 3 and p do a : cons (x, a),
3123 for x : 1 thru 5 while x < 3 or p do a : cons (x, a),
3126 for x : 1 thru 5 while x < 10 or 'z do a : cons (x, a),
3131 for x : 1 thru 5 do a : cons (if x then x else false, a),
3134 for x : 1 thru 5 while x < 3 do a : cons (if x then x else false, a),
3140 for p in [true, false] do
3141 push (bar (p), res),
3143 push (errcatch (bar ('z)), res),
3148 translate_or_lose (foo, bar, baz),
3155 (kill (foo, bar, baz), 0);
3158 /* Basic tests for error checking of translated return and go forms */
3160 (foo () := return (),
3164 (foo () := do return (1),
3165 translate_or_lose (foo),
3169 (foo () := block (return (2)),
3170 translate_or_lose (foo),
3178 (foo () := block (go (f ())),
3183 (foo () := do (go (1), return (false), 1, return (true)),
3184 translate_or_lose (foo),
3189 (foo () := block (block (go (x)), return (1), go (x), return (2), x, 3),
3190 translate_or_lose (foo),
3194 (foo () := block (go (end), return (0), end, 1),
3195 translate_or_lose (foo),
3202 /* Bug #4260: translate fails with go tag in final position */
3204 block ([translate : false, l1, l2],
3213 block (go (0), return (false), 0),
3214 block (go (a), return (false), a),
3215 block (go (done), return (false), done),
3216 block (go (b), return (false), b, 1),
3217 block (go (c), return (false), c, d),
3218 block (go (f), return (false), f, 'g),
3219 block (go (done), return (false), done, 'end),
3220 block (go (2), return (false), 1, return (true), 2, go (1))],
3224 translate_or_lose (foo),
3234 /* We had cases of incorrect number of argument evaluations when going
3235 * through MFUNCTION-CALL internally.
3238 (eval_string_lisp ("
3241 (setf (symbol-plist '$bar) '())"),
3245 block ([translate : false, v1, v2],
3246 foo () := block ([n : 0], bar (n : n + 1)),
3250 translate_or_lose (foo),
3254 [v2, is (v1 = v2)]);
3260 block ([translate : false, v1, v2],
3263 foo () := block ([n : 0], bar (n : n + 1)),
3269 translate_or_lose (foo),
3273 [v2, is (v1 = v2)]);
3279 block ([translate : false, bar, v1, v2],
3280 foo () := block ([n : 0], bar (n : n + 1)),
3282 bar : lambda ([q], q),
3286 translate_or_lose (foo),
3288 v2 : foo (), /* this used to yield 2 */
3290 [v2, is (v1 = v2)]);
3296 block ([translate : false, transrun : true, v1, v2],
3299 foo () := block ([n : 0], bar (n : n + 1), n),
3301 translate_or_lose (foo),
3305 v1 : foo (), /* this used to yield 1 */
3311 [v1, is (v1 = v2)]);
3317 block ([translate : false, transrun : true, v1, v2],
3318 foo () := block ([n : 0], bar (n : n + 1), n),
3320 translate_or_lose (foo),
3322 eval_string_lisp ("(defmspec $bar (q) (declare (ignore q)) 123)"),
3324 v1 : foo (), /* this used to yield 1 */
3330 [v1, is (v1 = v2)]);
3334 eval_string_lisp ("(setf (symbol-plist '$bar) '())"),
3342 /*** KILLING THESE FUNCTIONS SHOULD BE THE LAST TEST IN THIS FILE ***/
3343 (kill (translate_or_lose, compile_or_lose), 0);
3345 /*** THERE SHOULD BE NO TESTS BEYOND THIS POINT ***/