Ripped out deprecated logical VTABLES
[parrot.git] / src / ops / cmp.ops
blob42daf49a51180af1b6208457c8173ae62d508b31
1 /*
2  * $Id$
3 ** cmp.ops
4 */
6 =head1 NAME
8 cmp.ops - Comparison Opcodes
10 =cut
12 =head1 DESCRIPTION
14 Operations that compare two registers against each other.
15 Some of these operations affect control flow directly; others
16 do not.
18 When making changes to any ops file, run C<make bootstrap-ops> to regenerate
19 all generated ops files.
21 =cut
23 ###############################################################################
25 =head2 Flow control comparison operators
27 These operators branch based on the relationship between
28 their operands.
30 =over 4
32 =cut
34 ########################################
36 =item B<eq>(in INT, in INT, inconst LABEL)
38 =item B<eq>(in NUM, in NUM, inconst LABEL)
40 =item B<eq>(in STR, in STR, inconst LABEL)
42 =item B<eq>(invar PMC, invar PMC, inconst LABEL)
44 =item B<eq>(invar PMC, in INT, inconst LABEL)
46 =item B<eq>(invar PMC, in NUM, inconst LABEL)
48 =item B<eq>(invar PMC, in STR, inconst LABEL)
50 =item B<eq_str>(invar PMC, invar PMC, inconst LABEL)
52 =item B<eq_num>(invar PMC, invar PMC, inconst LABEL)
54 =item B<eq_addr>(in STR, in STR, inconst LABEL)
56 =item B<eq_addr>(invar PMC, invar PMC, inconst LABEL)
58 Branch if $1 is equal to $2. For PMCs this does a generic comparison,
59 whatever that is for the involved PMCs. Mixed PMC number/string
60 operands do a numeric or string comparison respectively.
62 B<eq_str> and B<eq_num> enforce string or number comparisons.
64 B<eq_addr> compares the address of the objects or strings.
66 =cut
68 inline op eq(in INT, in INT, inconst LABEL) :base_core {
69     if ($1 == $2) {
70         goto OFFSET($3);
71     }
74 inline op eq(in NUM, in NUM, inconst LABEL) :base_core {
75     if ($1 == $2) {
76         goto OFFSET($3);
77     }
80 op eq(in STR, in STR, inconst LABEL) :base_core {
81     if (Parrot_str_equal(interp, $1, $2)) {
82         goto OFFSET($3);
83     }
86 op eq(invar PMC, invar PMC, inconst LABEL) :base_core {
87     if (VTABLE_is_equal(interp, $1, $2)) {
88         goto OFFSET($3);
89     }
92 op eq(invar PMC, in INT, inconst LABEL) :base_core {
93     PMC * const temp = Parrot_pmc_new_temporary(interp, enum_class_Integer);
94     VTABLE_set_integer_native(interp, temp, $2);
96     if (VTABLE_is_equal(interp, $1, temp)) {
97         Parrot_pmc_free_temporary(interp, temp);
98         goto OFFSET($3);
99     }
101     Parrot_pmc_free_temporary(interp, temp);
104 op eq(invar PMC, in NUM, inconst LABEL) :base_core {
105     /*
106      * the get_number and get_string should probably
107      * be also replaced with code like above, as
108      * overriding the compare multi subs wouldn't
109      * have any effect with the current code
110      */
111     if (VTABLE_get_number(interp, $1) == $2) {
112         goto OFFSET($3);
113     }
116 op eq(invar PMC, in STR, inconst LABEL) :base_core {
117     if (Parrot_str_equal(interp, VTABLE_get_string(interp, $1), $2)) {
118         goto OFFSET($3);
119     }
122 op eq_str(invar PMC, invar PMC, inconst LABEL) :base_core {
123     if (VTABLE_is_equal_string(interp, $1, $2)) {
124         goto OFFSET($3);
125     }
128 op eq_num(invar PMC, invar PMC, inconst LABEL) :base_core {
129     if (VTABLE_is_equal_num(interp, $1, $2)) {
130         goto OFFSET($3);
131     }
134 op eq_addr(in STR, in STR, inconst LABEL) :base_core {
135     if ($1 == $2) {
136         goto OFFSET($3);
137     }
140 op eq_addr(invar PMC, invar PMC, inconst LABEL) :base_core {
141     if ($1 == $2) {
142         goto OFFSET($3);
143     }
146 ########################################
148 =item B<ne>(in INT, in INT, inconst LABEL)
150 =item B<ne>(in NUM, in NUM, inconst LABEL)
152 =item B<ne>(in STR, in STR, inconst LABEL)
154 =item B<ne>(invar PMC, invar PMC, inconst LABEL)
156 =item B<ne>(invar PMC, in INT, inconst LABEL)
158 =item B<ne>(invar PMC, in NUM, inconst LABEL)
160 =item B<ne>(invar PMC, in STR, inconst LABEL)
162 =item B<ne_str>(invar PMC, invar PMC, inconst LABEL)
164 =item B<ne_num>(invar PMC, invar PMC, inconst LABEL)
166 =item B<ne_addr>(in STR, in STR, inconst LABEL)
168 =item B<ne_addr>(invar PMC, invar PMC, inconst LABEL)
170 Branch if $1 is not equal to $2.
172 =cut
174 inline op ne(in INT, in INT, inconst LABEL) :base_core {
175     if ($1 != $2) {
176         goto OFFSET($3);
177     }
180 inline op ne(in NUM, in NUM, inconst LABEL) :base_core {
181     if ($1 != $2) {
182         goto OFFSET($3);
183     }
186 op ne(in STR, in STR, inconst LABEL) :base_core {
187     if (Parrot_str_not_equal(interp, $1, $2)) {
188         goto OFFSET($3);
189     }
192 op ne(invar PMC, invar PMC, inconst LABEL) :base_core {
193     if (!VTABLE_is_equal(interp, $1, $2)) {
194         goto OFFSET($3);
195     }
198 op ne(invar PMC, in INT, inconst LABEL) :base_core {
199     PMC * const temp = Parrot_pmc_new_temporary(interp, enum_class_Integer);
200     VTABLE_set_integer_native(interp, temp, $2);
202     if (!VTABLE_is_equal(interp, $1, temp)) {
203         Parrot_pmc_free_temporary(interp, temp);
204         goto OFFSET($3);
205     }
207     Parrot_pmc_free_temporary(interp, temp);
210 op ne(invar PMC, in NUM, inconst LABEL) :base_core {
211     if (VTABLE_get_number(interp, $1) != $2) {
212         goto OFFSET($3);
213     }
216 op ne(invar PMC, in STR, inconst LABEL) :base_core {
217     if (Parrot_str_not_equal(interp, VTABLE_get_string(interp, $1), $2)) {
218         goto OFFSET($3);
219     }
222 op ne_str(invar PMC, invar PMC, inconst LABEL) :base_core {
223     if (VTABLE_cmp_string(interp, $1, $2) != 0) {
224         goto OFFSET($3);
225     }
228 op ne_num(invar PMC, invar PMC, inconst LABEL) :base_core {
229     if (VTABLE_cmp_num(interp, $1, $2) != 0) {
230         goto OFFSET($3);
231     }
234 op ne_addr(in STR, in STR, inconst LABEL) :base_core {
235     if ($1 != $2) {
236         goto OFFSET($3);
237     }
240 op ne_addr(invar PMC, invar PMC, inconst LABEL) :base_core {
241     if ($1 != $2) {
242         goto OFFSET($3);
243     }
246 ########################################
248 =item B<lt>(in INT, in INT, inconst LABEL)
250 =item B<lt>(in NUM, in NUM, inconst LABEL)
252 =item B<lt>(in STR, in STR, inconst LABEL)
254 =item B<lt>(invar PMC, invar PMC, inconst LABEL)
256 =item B<lt>(invar PMC, in INT, inconst LABEL)
258 =item B<lt>(invar PMC, in NUM, inconst LABEL)
260 =item B<lt>(invar PMC, in STR, inconst LABEL)
262 =item B<lt_str>(invar PMC, invar PMC, inconst LABEL)
264 =item B<lt_num>(invar PMC, invar PMC, inconst LABEL)
266 Branch if $1 is less than $2.
268 =cut
270 inline op lt(in INT, in INT, inconst LABEL) :base_core {
271     if ($1 < $2) {
272         goto OFFSET($3);
273     }
276 inline op lt(in NUM, in NUM, inconst LABEL) :base_core {
277     if ($1 < $2) {
278         goto OFFSET($3);
279     }
282 op lt(in STR, in STR, inconst LABEL) :base_core {
283     if (Parrot_str_compare(interp, $1, $2) < 0) {
284         goto OFFSET($3);
285     }
288 op lt(invar PMC, invar PMC, inconst LABEL) :base_core {
289     if (VTABLE_cmp(interp, $1, $2) < 0) {
290         goto OFFSET($3);
291     }
294 op lt(invar PMC, in INT, inconst LABEL) :base_core {
295     PMC * const temp = Parrot_pmc_new_temporary(interp, enum_class_Integer);
296     VTABLE_set_integer_native(interp, temp, $2);
298     if (VTABLE_cmp(interp, $1, temp) < 0) {
299         Parrot_pmc_free_temporary(interp, temp);
300         goto OFFSET($3);
301     }
303     Parrot_pmc_free_temporary(interp, temp);
306 op lt(invar PMC, in NUM, inconst LABEL) :base_core {
307     if (VTABLE_get_number(interp, $1) < $2) {
308         goto OFFSET($3);
309     }
312 op lt(invar PMC, in STR, inconst LABEL) :base_core {
313     if (Parrot_str_compare(interp, VTABLE_get_string(interp, $1), $2) < 0) {
314         goto OFFSET($3);
315     }
318 op lt_str(invar PMC, invar PMC, inconst LABEL) :base_core {
319     if (VTABLE_cmp_string(interp, $1, $2) < 0) {
320         goto OFFSET($3);
321     }
324 op lt_num(invar PMC, invar PMC, inconst LABEL) :base_core {
325     if (VTABLE_cmp_num(interp, $1, $2) < 0) {
326         goto OFFSET($3);
327     }
330 ########################################
332 =item B<le>(in INT, in INT, inconst LABEL)
334 =item B<le>(in NUM, in NUM, inconst LABEL)
336 =item B<le>(in STR, in STR, inconst LABEL)
338 =item B<le>(invar PMC, invar PMC, inconst LABEL)
340 =item B<le>(invar PMC, in INT, inconst LABEL)
342 =item B<le>(invar PMC, in NUM, inconst LABEL)
344 =item B<le>(invar PMC, in STR, inconst LABEL)
346 =item B<le_str>(invar PMC, invar PMC, inconst LABEL)
348 =item B<le_num>(invar PMC, invar PMC, inconst LABEL)
350 Branch if $1 is less than or equal to $2.
352 =cut
354 inline op le(in INT, in INT, inconst LABEL) :base_core {
355     if ($1 <= $2) {
356         goto OFFSET($3);
357     }
360 inline op le(in NUM, in NUM, inconst LABEL) :base_core {
361     if ($1 <= $2) {
362         goto OFFSET($3);
363     }
366 op le(in STR, in STR, inconst LABEL) :base_core {
367     if (Parrot_str_compare(interp, $1, $2) <= 0) {
368         goto OFFSET($3);
369     }
372 op le(invar PMC, invar PMC, inconst LABEL) :base_core {
373     if (VTABLE_cmp(interp, $1, $2) <= 0) {
374         goto OFFSET($3);
375     }
378 op le(invar PMC, in INT, inconst LABEL) :base_core {
379     PMC * const temp = Parrot_pmc_new_temporary(interp, enum_class_Integer);
380     VTABLE_set_integer_native(interp, temp, $2);
382     if (VTABLE_cmp(interp, $1, temp) <= 0) {
383         Parrot_pmc_free_temporary(interp, temp);
384         goto OFFSET($3);
385     }
387     Parrot_pmc_free_temporary(interp, temp);
390 op le(invar PMC, in NUM, inconst LABEL) :base_core {
391     if (VTABLE_get_number(interp, $1) <= $2) {
392         goto OFFSET($3);
393     }
396 op le(invar PMC, in STR, inconst LABEL) :base_core {
397     if (Parrot_str_compare(interp, VTABLE_get_string(interp, $1), $2) <= 0) {
398         goto OFFSET($3);
399     }
402 op le_str(invar PMC, invar PMC, inconst LABEL) :base_core {
403     if (VTABLE_cmp_string(interp, $1, $2) <= 0) {
404         goto OFFSET($3);
405     }
408 op le_num(invar PMC, invar PMC, inconst LABEL) :base_core {
409     if (VTABLE_cmp_num(interp, $1, $2) <= 0) {
410         goto OFFSET($3);
411     }
414 ########################################
416 =item B<gt>(invar PMC, invar PMC, inconst LABEL)
418 =item B<gt>(invar PMC, in INT, inconst LABEL)
420 =item B<gt>(invar PMC, in NUM, inconst LABEL)
422 =item B<gt>(invar PMC, in STR, inconst LABEL)
424 =item B<gt_str>(invar PMC, invar PMC, inconst LABEL)
426 =item B<gt_num>(invar PMC, invar PMC, inconst LABEL)
428 Branch if $1 is greater than $2.
430 =cut
432 op gt(invar PMC, invar PMC, inconst LABEL) :base_core {
433     if (VTABLE_cmp(interp, $1, $2) > 0) {
434         goto OFFSET($3);
435     }
438 op gt(invar PMC, in INT, inconst LABEL) :base_core {
439     PMC * const temp = Parrot_pmc_new_temporary(interp, enum_class_Integer);
440     VTABLE_set_integer_native(interp, temp, $2);
442     if (VTABLE_cmp(interp, $1, temp) > 0) {
443         Parrot_pmc_free_temporary(interp, temp);
444         goto OFFSET($3);
445     }
447     Parrot_pmc_free_temporary(interp, temp);
450 op gt(invar PMC, in NUM, inconst LABEL) :base_core {
451     if (VTABLE_get_number(interp, $1) > $2) {
452         goto OFFSET($3);
453     }
456 op gt(invar PMC, in STR, inconst LABEL) :base_core {
457     if (Parrot_str_compare(interp, VTABLE_get_string(interp, $1), $2) > 0) {
458         goto OFFSET($3);
459     }
462 op gt_str(invar PMC, invar PMC, inconst LABEL) :base_core {
463     if (VTABLE_cmp_string(interp, $1, $2) > 0) {
464         goto OFFSET($3);
465     }
468 op gt_num(invar PMC, invar PMC, inconst LABEL) :base_core {
469     if (VTABLE_cmp_num(interp, $1, $2) > 0) {
470         goto OFFSET($3);
471     }
474 ########################################
476 =item B<ge>(invar PMC, invar PMC, inconst LABEL)
478 =item B<ge>(invar PMC, in INT, inconst LABEL)
480 =item B<ge>(invar PMC, in NUM, inconst LABEL)
482 =item B<ge>(invar PMC, in STR, inconst LABEL)
484 =item B<ge_str>(invar PMC, invar PMC, inconst LABEL)
486 =item B<ge_num>(invar PMC, invar PMC, inconst LABEL)
488 Branch if $1 is greater than or equal to $2.
490 =cut
492 op ge(invar PMC, invar PMC, inconst LABEL) :base_core {
493     if (VTABLE_cmp(interp, $1, $2) >= 0) {
494         goto OFFSET($3);
495     }
498 op ge(invar PMC, in INT, inconst LABEL) :base_core {
499     PMC * const temp = Parrot_pmc_new_temporary(interp, enum_class_Integer);
500     VTABLE_set_integer_native(interp, temp, $2);
502     if (VTABLE_cmp(interp, $1, temp) >= 0) {
503         Parrot_pmc_free_temporary(interp, temp);
504         goto OFFSET($3);
505     }
507     Parrot_pmc_free_temporary(interp, temp);
510 op ge(invar PMC, in NUM, inconst LABEL) :base_core {
511     if (VTABLE_get_number(interp, $1) >= $2) {
512         goto OFFSET($3);
513     }
516 op ge(invar PMC, in STR, inconst LABEL) :base_core {
517     if (Parrot_str_compare(interp, VTABLE_get_string(interp, $1), $2) >= 0) {
518         goto OFFSET($3);
519     }
522 op ge_str(invar PMC, invar PMC, inconst LABEL) :base_core {
523     if (VTABLE_cmp_string(interp, $1, $2) >= 0) {
524         goto OFFSET($3);
525     }
528 op ge_num(invar PMC, invar PMC, inconst LABEL) :base_core {
529     if (VTABLE_cmp_num(interp, $1, $2) >= 0) {
530         goto OFFSET($3);
531     }
534 ########################################
536 =item B<if_null>(invar PMC, inconst LABEL)
538 Branch to $2 if $1 is a NULL PMC.
540 =item B<if_null>(invar STR, inconst LABEL)
542 Branch to $2 if $1 is a NULL STRING.
544 =cut
546 op if_null(invar PMC, inconst LABEL) {
547     if (PMC_IS_NULL($1)) {
548         goto OFFSET($2);
549     }
552 op if_null(invar STR, inconst LABEL) {
553     if (STRING_IS_NULL($1)) {
554         goto OFFSET($2);
555     }
558 ########################################
560 =item B<unless_null>(invar PMC, inconst LABEL)
562 Branch to $2 if $1 is I<not> a NULL PMC.
564 =item B<unless_null>(invar STR, inconst LABEL)
566 Branch to $2 if $1 is I<not> a NULL STRING.
568 =cut
570 op unless_null(invar PMC, inconst LABEL) {
571     if (!PMC_IS_NULL($1)) {
572         goto OFFSET($2);
573     }
576 op unless_null(invar STR, inconst LABEL) {
577     if (!STRING_IS_NULL($1)) {
578         goto OFFSET($2);
579     }
582 =back
584 =cut
587 ###############################################################################
589 =head2 Non-flow control comparison ops
591 These ops do comparisons and truth testing without doing flow control.
593 =over 4
595 =item B<cmp>(out INT, in INT, in INT)
597 =item B<cmp>(out INT, in NUM, in NUM)
599 =item B<cmp>(out INT, in STR, in STR)
601 =item B<cmp>(out INT, invar PMC, invar PMC)
603 =item B<cmp>(out INT, invar PMC, in INT)
605 =item B<cmp>(out INT, invar PMC, in NUM)
607 =item B<cmp>(out INT, invar PMC, in STR)
609 =item B<cmp_str>(out INT, invar PMC, invar PMC)
611 =item B<cmp_num>(out INT, invar PMC, invar PMC)
613 Sets $1 to -1 if $2 < $3, +1 if $2 > $3, and 0 otherwise.
615 =cut
617 inline op cmp(out INT, in INT, in INT) :base_core {
618     $1 = $2 < $3 ? -1 :
619          $2 > $3 ? +1 :
620          0;
623 inline op cmp(out INT, in NUM, in NUM) :base_core {
624     $1 = $2 < $3 ? -1 :
625          $2 > $3 ? +1 :
626          0;
629 inline op cmp(out INT, in STR, in STR) :base_core {
630     $1 = Parrot_str_compare(interp, $2, $3);
633 inline op cmp(out INT, invar PMC, invar PMC) :base_core {
634     $1 = VTABLE_cmp(interp, $2, $3);
637 inline op cmp(out INT, invar PMC, in INT) :base_core {
638     const INTVAL l = VTABLE_get_integer(interp, $2);
639     $1 = l < $3 ? -1 :
640          l > $3 ? +1 :
641          0;
644 inline op cmp(out INT, invar PMC, in NUM) :base_core {
645     const FLOATVAL l = VTABLE_get_number(interp, $2);
646     $1 = l < $3 ? -1 :
647          l > $3 ? +1 :
648          0;
651 inline op cmp(out INT, invar PMC, in STR) :base_core {
652     STRING* const l = VTABLE_get_string(interp, $2);
653     $1 = Parrot_str_compare(interp, l, $3);
656 inline op cmp_str(out INT, invar PMC, invar PMC) :base_core {
657     $1 = VTABLE_cmp_string(interp, $2, $3);
660 inline op cmp_num(out INT, invar PMC, invar PMC) :base_core {
661     $1 = VTABLE_cmp_num(interp, $2, $3);
664 =item B<cmp_pmc>(out PMC, invar PMC, invar PMC)
666 Does the same thing as the other cmp_* variants, but puts a PMC in $1.  This is
667 useful for avoiding the semipredicate problem in HLLs where two aggregate PMCs
668 are not always comparable.
670 =cut
672 inline op cmp_pmc(out PMC, invar PMC, invar PMC) :base_core {
673     $1 = VTABLE_cmp_pmc(interp, $2, $3);
676 ########################################
678 =item B<issame>(out INT, invar PMC, invar PMC)
680 =item B<issame>(out INT, in STR, in STR)
682 Sets $1 to 1 or 0, depending on the identity of the 2 objects.
683 The identity is the PMCs memory address.
685 =item B<isntsame>(out INT, invar PMC, invar PMC)
687 =item B<isntsame>(out INT, in STR, in STR)
689 Sets $1 to 0 or 1, depending on the identity of the 2 objects.
691 =item B<istrue>(out INT, invar PMC)
693 Sets $1 to 1 or 0, depending on whether $2 is true or not.
695 =item B<isfalse>(out INT, invar PMC)
697 Sets $1 to 1 or 0, depending on whether $2 is false or not.
699 =item B<isnull>(out INT, in PMC)
701 Sets $1 to 1 if the object is null, 0 otherwise.
703 =item B<isnull>(out INT, in STR)
705 Sets $1 to 1 if the string is null, 0 otherwise.
707 =cut
709 inline op issame(out INT, invar PMC, invar PMC) {
710     if ($2 == $3)
711         $1 = 1;
712     else
713         $1 = VTABLE_is_same(interp, $2, $3);
716 inline op issame(out INT, in STR, in STR) {
717     $1 = $2 == $3;
720 inline op isntsame(out INT, invar PMC, invar PMC) {
721     if ($2 == $3)
722         $1 = 0;
723     else
724         $1 = !VTABLE_is_same(interp, $2, $3);
727 inline op isntsame(out INT, in STR, in STR) {
728     $1 = $2 != $3;
731 inline op istrue(out INT, invar PMC) {
732     $1 = VTABLE_get_bool(interp, $2);
735 inline op isfalse(out INT, invar PMC) {
736     $1 = !VTABLE_get_bool(interp, $2);
739 inline op isnull(out INT, in PMC) {
740     $1 = PMC_IS_NULL($2);
743 inline op isnull(out INT, in STR) {
744     $1 = STRING_IS_NULL($2);
747 =item B<isgt>(out INT, in INT, in INT)
749 =item B<isgt>(out INT, in NUM, in NUM)
751 =item B<isgt>(out INT, in STR, in STR)
753 These 3 opcodes are valid, but create as their reverse.
755 =item B<isgt>(out INT, invar PMC, invar PMC)
757 Sets $1 to 1 if $2 is greater than $3.
759 =cut
761 inline op isgt(out INT, invar PMC, invar PMC) {
762     $1 = (VTABLE_cmp(interp, $2, $3) > 0);
765 =item B<isge>(out INT, in INT, in INT)
767 =item B<isge>(out INT, in NUM, in NUM)
769 =item B<isge>(out INT, in STR, in STR)
771 These 3 opcodes are valid, but create as their reverse.
773 =item B<isge>(out INT, invar PMC, invar PMC)
775 Sets $1 to 1 if $2 is greater than or equal to $3.
777 =cut
779 inline op isge(out INT, invar PMC, invar PMC) {
780     $1 = (VTABLE_cmp(interp, $2, $3) >= 0);
783 =item B<isle>(out INT, in INT, in INT)
785 =item B<isle>(out INT, in NUM, in NUM)
787 =item B<isle>(out INT, in STR, in STR)
789 =item B<isle>(out INT, invar PMC, invar PMC)
791 Sets $1 to 1 if $2 is less than or equal to $3.
793 =cut
795 inline op isle(out INT, in INT, in INT) {
796     $1 = $2 <= $3;
799 inline op isle(out INT, in NUM, in NUM) {
800     $1 = $2 <= $3;
803 inline op isle(out INT, in STR, in STR) {
804     $1 = Parrot_str_compare(interp, $2, $3) <= 0;
807 inline op isle(out INT, invar PMC, invar PMC) {
808     $1 = (VTABLE_cmp(interp, $2, $3) <= 0);
811 =item B<islt>(out INT, in INT, in INT)
813 =item B<islt>(out INT, in NUM, in NUM)
815 =item B<islt>(out INT, in STR, in STR)
817 =item B<islt>(out INT, invar PMC, invar PMC)
819 Sets $1 to 1 if $2 is less than $3.
821 =cut
823 inline op islt(out INT, in INT, in INT) {
824     $1 = ($2 < $3) ? 1 : 0;
827 inline op islt(out INT, in NUM, in NUM) {
828     $1 = $2 < $3;
831 inline op islt(out INT, in STR, in STR) {
832     $1 = Parrot_str_compare(interp, $2, $3) < 0;
835 inline op islt(out INT, invar PMC, invar PMC) {
836     $1 = (VTABLE_cmp(interp, $2, $3) < 0);
839 =item B<iseq>(out INT, in INT, in INT)
841 =item B<iseq>(out INT, in NUM, in NUM)
843 =item B<iseq>(out INT, in STR, in STR)
845 =item B<iseq>(out INT, invar PMC, invar PMC)
847 Sets $1 to 1 if $2 is equal to $3.
849 =cut
851 inline op iseq(out INT, in INT, in INT) {
852     $1 = ($2 == $3) ? 1 : 0;
855 inline op iseq(out INT, in NUM, in NUM) {
856     $1 = $2 == $3;
859 inline op iseq(out INT, in STR, in STR) {
860     $1 = (Parrot_str_equal(interp, $2, $3) ? 1 : 0);
863 inline op iseq(out INT, invar PMC, invar PMC) {
864     if (&$2 == &$3)
865         $1 = 1;
866     else
867         $1 = VTABLE_is_equal(interp, $2, $3);
870 =item B<isne>(out INT, in INT, in INT)
872 =item B<isne>(out INT, in NUM, in NUM)
874 =item B<isne>(out INT, in STR, in STR)
876 =item B<isne>(out INT, invar PMC, invar PMC)
878 Sets $1 to 1 if $2 is not equal to $3.
880 =cut
882 inline op isne(out INT, in INT, in INT) {
883     $1 = ($2 == $3) ? 0 : 1;
886 inline op isne(out INT, in NUM, in NUM) {
887     $1 = $2 != $3;
890 inline op isne(out INT, in STR, in STR) {
891     $1 = (Parrot_str_not_equal(interp, $2, $3) ? 1 : 0);
894 inline op isne(out INT, invar PMC, invar PMC) {
895     if (&$2 == &$3)
896         $1 = 0;
897     else
898         $1 = !VTABLE_is_equal(interp, $2, $3);
901 =back
903 =cut
906 ###############################################################################
908 =head2 Logical operations
910 These operations apply logical functions to their arguments.
912 =over 4
914 =cut
916 ########################################
918 =item B<and>(out INT, in INT, in INT)
920 =item B<and>(invar PMC, invar PMC, invar PMC)
922 Short-circuiting logical and.  Returns $2 if it's false, else returns $3.
924 =cut
926 inline op and(out INT, in INT, in INT) :base_core {
927     $1 = $2 ? $3 : $2;
930 inline op and(invar PMC, invar PMC, invar PMC) :base_core {
931     $1 = VTABLE_get_bool(interp, $2) ? $3 : $2;
934 ########################################
936 =item B<not>(inout INT)
938 =item B<not>(invar PMC)
940 Set the boolean state of $1 to the opposite of the boolean state from $1.
942 =item B<not>(out INT, in INT)
944 =item B<not>(out PMC, invar PMC)
946 =cut
948 inline op not(inout INT) :base_core {
949     $1 = ! $1;
952 inline op not(out INT, in INT) :base_core {
953     $1 = ! $2;
956 inline op not(invar PMC) :base_core {
957     VTABLE_set_bool(interp, $1, !VTABLE_get_bool(interp, $1));
960 inline op not(out PMC, invar PMC) :base_core {
961     $1 = Parrot_pmc_new(interp, VTABLE_type(interp, $2));
962     VTABLE_set_bool(interp, $1, (!VTABLE_get_bool(interp, $2)));
965 ########################################
967 =item B<or>(out INT, in INT, in INT)
969 =item B<or>(invar PMC, invar PMC, invar PMC)
971 Short-circuiting logical or.  Returns $2 if it's true, else returns $3.
973 =cut
975 inline op or(out INT, in INT, in INT) :base_core {
976     $1 = $2 ? $2 : $3;
979 inline op or(invar PMC, invar PMC, invar PMC) :base_core {
980     $1 = VTABLE_get_bool(interp, $2) ? $2 : $3;
983 ########################################
985 =item B<xor>(out INT, in INT, in INT)
987 =item B<xor>(invar PMC, invar PMC, invar PMC)
989 Logical xor.  Returns $2 if it's true and $3 isn't,
990 returns $3 if it's true and $2 isn't, else returns false.
992 =cut
994 inline op xor(out INT, in INT, in INT) :base_core {
995     $1 = ($2 && ! $3) ? $2 : ($3 && ! $2) ? $3 : 0;
998 inline op xor(invar PMC, invar PMC, invar PMC) :base_core {
999     const INTVAL a = VTABLE_get_bool(interp, $2);
1000     const INTVAL b = VTABLE_get_bool(interp, $3);
1001     if (a && ! b)
1002         $1 = $2;
1003     else
1004         if (b && ! a)
1005             $1 = $3 ;
1006         else{
1007             $1 = Parrot_pmc_new(interp, VTABLE_type(interp, $2));
1008             VTABLE_set_bool(interp, $1, 0);
1009         }
1012 =back
1014 =cut
1017 ###############################################################################
1019 =head1 COPYRIGHT
1021 Copyright (C) 2001-2010, Parrot Foundation.
1023 =head1 LICENSE
1025 This program is free software. It is subject to the same license
1026 as the Parrot interpreter itself.
1028 =cut
1031  * Local variables:
1032  *   c-file-style: "parrot"
1033  * End:
1034  * vim: expandtab shiftwidth=4:
1035  */