8 print <<"END_OF_HEADER";
11 # This file generated automatically by '$0'
16 $macros{DOMAIN_ERROR} = <<'END_OF_PIR';
21 '+' => [ 'Add', '%1 = %1 + %2' ],
22 '*' => [ 'Power', << 'END_PIR' ],
23 # XXX This is too restrictive. Need better tests
24 if %1 >= 0 goto power_ok
34 '\x{d7}' => [ 'Multiply', '%1 = %1 * %2' ],
35 '\x{f7}' => [ 'Divide', '%1 = %1 / %2' ],
36 '\u2212' => [ 'Subtract', '%1 = %1 - %2' ],
37 '\u2308' => [ 'Maximum', <<'END_PIR' ],
38 if %1 > %2 goto maximum_done
43 '\u230a' => [ 'Minimum', <<'END_PIR' ],
44 if %1 < %2 goto minimum_done
50 my $template = <<'END_OF_TEMPLATE';
54 # any registers #'d 100 or higher are used here for temporary conversions
55 # to other types required by the various opcodes. XXX This should go away
56 # Once PMI ports his lovely new perl6 code back into APL.
58 .sub "__load_inlinetable" :load :init
60 store_global "APL", "%pirtable", $P0
63 set_hll_global ['APL';'Grammar';'Actions'], '%inlinetable', itable
65 # special-purpose parrot ops here
66 itable['dyadic:<'] = <<'END_PIR'
67 $I1 = islt %0, %1 # dyadic:< (less than)
71 itable['dyadic:>'] = <<'END_PIR'
72 $I1 = isgt %0, %1 # dyadic:> (greater than)
76 itable['dyadic:='] = <<'END_PIR'
77 $I1 = iseq %0, %1 # dyadic:= (equals)
81 itable[unicode:"dyadic:\u2227"] = <<'END_PIR'
82 $I0 = %0 # dyadic:\u2227 (and)
88 itable[unicode:"dyadic:\u2228"] = <<'END_PIR'
89 $I0 = %0 # dyadic:\u2228 (or)
95 itable[unicode:"dyadic:\u2260"] = <<'END_PIR'
96 $I1 = isne %0, %1 # dyadic:\u2260 (not equal)
100 itable[unicode:"dyadic:\u2264"] = <<'END_PIR'
101 $I1 = isle %0, %1 # dyadic:\u2264 (not greater than)
105 itable[unicode:"dyadic:\u2265"] = <<'END_PIR'
106 $I1 = isge %0, %1 # dyadic:\u2265 (not less than)
110 itable[unicode:"dyadic:\u2371"] = <<'END_PIR'
111 $I0 = %0 # dyadic:\u2371 (nor)
118 itable[unicode:"dyadic:\u2372"] = <<'END_PIR'
119 $I0 = %0 # dyadic:\u2372 (nand)
126 itable['monadic:+'] = " %r = %0" # conjugate
127 itable['monadic:|'] = " %t = abs %0" # magnitude
128 itable['monadic:!'] = <<'END_PIR'
129 $I1 = %0 # monadic:! (factorial)
134 itable['monadic:*'] = " %t = exp %0" # exp
135 itable[unicode:"monadic:\x{d7}"] = <<'END_PIR'
136 $N1 = %0 # monadic:\x{d7} (signum)
137 $I1 = cmp_num $N1, 0.0
140 itable[unicode:"monadic:\x{f7}"] = <<'END_PIR'
141 $N1 = %0 # monadic:\x{f7} (reciprocal)
146 itable[unicode:"monadic:\u2212"] = " %t = neg %0" # negate
147 itable[unicode:"monadic:\u2308"] = <<'END_PIR'
148 $N1 = %0 # monadic:\u2308 (ceiling)
153 itable[unicode:"monadic:\u230a"] = <<'END_PIR'
154 $N1 = %0 # monadic:\u230a (floor)
159 itable[unicode:"monadic:\u235f"] = " %t = ln %0"
162 itable[unicode:"monadic:\u25cb"] = " %t = %0 * 3.14159265358979323846"
165 itable[unicode:"monadic:\u2373"] = <<'END_PIR' # index of
166 #XXX hack all the _1's need the same, generated unique number.
167 %r = new 'APLVector' # monadic:\u2373 (index of)
172 if $I0 > $I2 goto loop_done_1
189 $I0 = does arg, 'array'
190 if $I0 goto print_vector
196 .local pmc shape, iter
197 .local string value_type, old_type
198 value_type = 'String'
199 iter = new 'Iterator', arg
200 shape = arg.'get_shape'()
202 if $I0 == 2 goto print_2D
203 # XXX assume 1d otherwise.
204 unless iter goto iter_end
206 old_type = value_type
209 unless iter goto iter_end
210 value_type = typeof value
211 if value_type != 'String' goto print_space
212 if old_type != value_type goto print_space
221 .local int row_size, pos, newline
224 iter = new 'Iterator', arg
225 value_type = 'String'
226 unless iter goto loop_end_2d
229 if pos != row_size goto cont_2d
234 old_type = value_type
237 unless iter goto loop_end_2d
238 value_type = typeof value
239 if newline goto print_newline
240 if value_type != 'String' goto print_space_2d
241 if old_type != value_type goto print_space_2d
244 print_space_2d: # don't print a space if we're about to end a row
245 if newline goto print_newline
250 if newline==0 goto continue_2d
260 if value >= 0.0 goto print_value_1
261 result .= unicode:"\u207b"
277 .param pmc args :slurpy
278 .local pmc vector, iter
279 vector = new 'APLVector'
280 if null args goto iter_end
281 iter = new 'Iterator', args
283 unless iter goto iter_end
294 vector = new 'APLVector'
298 unless $I0 < $I1 goto loop_end
299 $S0 = substr s, $I0, 1
308 # XXX - the first argument to this multi sub should be some variant of
309 # integer - but if you set it to Integer or int, the program dies with
310 # 'Method not found.' or dispatches to the wrong method.
312 .sub unicode:"dyadic:\u2296" :multi(pmc, APLVector) # rotate
316 if op1 == 0 goto nothing
320 # shift off the beginning and push onto the end.
327 # pop off the end and unshift onto the beginning
338 .sub 'dyadic:!' # binomial coefficient
354 .sub unicode:"dyadic:\u2373" :multi(APLVector, APLVector) # index of
358 .local pmc iter_one, iter_two
359 .local pmc item_one, item_two
367 result = new 'APLVector'
369 iter_two = new 'Iterator', op2
371 unless iter_two goto loop_two_end
372 item_two = shift iter_two
373 iter_one = new 'Iterator', op1
374 pos_one = 0 # parrot's 0 == APL's 1
376 unless iter_one goto loop_one_end
377 item_one = shift iter_one
379 if item_one != item_two goto loop_one
381 # only need to find one, go back to outer loop.
384 # if we get this far, there was no match.
385 push result, not_found
393 .sub unicode:"dyadic:\u2373" :multi(APLVector, Float) # index of
398 result = new 'APLVector'
407 iter = new 'Iterator', op1
409 unless iter goto no_gots
410 value_at = shift iter
411 if value_at == op2 goto got_it
419 push result, not_there
423 .sub unicode:"dyadic:\u25cb" # circle
427 if $I1 == 0 goto zero
430 if $I1 == 3 goto three
431 if $I1 == 4 goto four
432 if $I1 == 5 goto five
434 if $I1 == 7 goto seven
435 if $I1 == -1 goto neg_one
436 if $I1 == -2 goto neg_two
437 if $I1 == -3 goto neg_three
438 if $I1 == -4 goto neg_four
439 if $I1 == -5 goto neg_five
440 if $I1 == -6 goto neg_six
441 if $I1 == -7 goto neg_seven
487 # These next three are implemented in terms of the available parrot opcodes.
488 neg_five: # arcsinh(x) = ln(x+sqrt(x*x+1))
495 neg_six: # arccosh(x) = ln(x+sqrt(x-1)*sqrt(x+1))
504 neg_seven: # arctanh(x) = .5 * (ln (1+x) - ln (1 -x))
514 .sub unicode:"dyadic:\u235f" # logarithm
523 # This somewhat convoluted based the description from the old APL/360 manual
524 .sub 'dyadic:|' # logarithm
527 if op1 == 0 goto zero_LHS
535 if op2 < 0 goto neg_RHS
541 .sub 'monadic:~' # not
543 # XXX is domain only 0,1?
551 .sub unicode:"monadic:\u233d" :multi(APLVector) # reverse
554 .local pmc result,iter
555 result = new 'APLVector'
556 iter = new 'Iterator', op1
559 unless iter goto done
567 .sub 'dyadic:~' :multi(APLVector, APLVector) # without
572 result = new 'APLVector'
574 .local pmc iter1,iter2
575 iter1 = new 'Iterator', op1
578 unless iter1 goto outer_done
581 iter2 = new 'Iterator', op2
583 unless iter2 goto inner_done
585 if $P1 == $P2 goto outer_loop # result must be without this.
596 .sub unicode:"monadic:\u2191" # first
602 .sub unicode:"dyadic:\u2191" :multi (Float, APLVector) # take
607 result = new 'APLVector'
610 iter = new 'Iterator', op2
612 if op1 >= 0 goto pos_loop
613 iter = 4 # ITERATE_FROM_END
616 if op1 == 0 goto done
617 unless iter goto done
619 $P1 = pop op2 # have to pop when iterating from end.
626 if op1 == 0 goto done
627 unless iter goto done
639 .sub unicode:"dyadic:\u2193" :multi (Float, APLVector) # drop
643 if op1 < 0 goto neg_loop
646 if op1 == 0 goto done
647 $P1 = shift op2 # ignore p1, we're discarding it
652 if op1 == 0 goto done
653 $P1 = pop op2 # ignore p1, we're discarding it
661 .sub unicode:"monadic:\u2374" :multi (Float) # shape
665 result = new 'APLVector'
669 .sub unicode:"monadic:\u2374" :multi (APLVector) # shape
671 .return op1.'get_shape'()
674 .sub unicode:"dyadic:\u2374" :multi (APLVector,APLVector) # reshape
678 # XXX is a clone needed here?
683 .sub unicode:"dyadic:\u2374" :multi (APLVector,Float) # reshape
687 # Convert the scalar into a vector and reshape it.
688 $P1 = new 'APLVector'
695 .sub unicode:"monadic:\u2355" #format
700 result = new 'APLVector'
704 if $I0 >= $I1 goto loop_end
705 $S1 = substr $S0, $I0, 1
713 .sub unicode:"monadic:\u2395\u2190" # quad output
723 # Generate all variants for scalar dyadic ops.
725 [ 'Float', 'Float' ],
726 [ 'Float', 'APLVector' ],
727 [ 'APLVector', 'Float' ],
728 [ 'APLVector', 'APLVector' ],
731 foreach my $operator ( keys %scalar ) {
732 my ( $name, $code ) = @{ $scalar{$operator} };
733 foreach my $types (@type_pairs) {
734 my ( $type1, $type2 ) = @$types;
736 $template .= <<"END_PREAMBLE
";
740 .sub unicode:"dyadic
:$operator" :multi ( $type1, $type2 )
745 if ( $type1 eq "Float
" && $type2 eq "Float
" ) {
748 $template .= interpolate( $code, 'op1', 'op2' );
750 elsif ( $type1 eq "APLVector
" && $type2 eq "APLVector
" ) {
753 $template .= << 'END_PIR';
754 # Verify Shapes conform.
757 if $I1 == $I2 goto good
760 # Create a result vector
762 result = new 'APLVector'
763 # Loop through each vector, doing the ops.
764 .local pmc iter1, iter2
765 iter1 = new 'Iterator', op1
766 iter2 = new 'Iterator', op2
768 unless iter1 goto loop_done
772 if $S1 == 'String' goto bad_args
774 if $S2 == 'String' goto bad_args
781 $template .= interpolate( $code, '$P1', '$P2' );
783 $template .= << 'END_PIR';
788 # return the result vector
796 my ( $vector, $scalar, @order );
797 if ( $type1 eq 'APLVector' ) {
800 @order = qw/ $P1 $P2 /;
805 @order = qw/ $P2 $P1 /;
808 $template .= << "END_PIR
";
809 # Create a result vector
811 result = new 'APLVector'
812 # Loop through each vector, doing the ops.
814 iter1 = new 'Iterator', $vector
816 unless iter1 goto loop_done
819 if \$S1 != 'String' goto got_args
825 $template .= interpolate( $code, @order );
827 $template .= 'push result, ' . $order[0] . "\n";
829 $template .= << 'END_PIR';
832 # return the result vector
837 $template .= <<"END_POSTAMBLE"
838 .return (op1
) # might be pre-empted
844 # Substitute all macros
845 foreach my $macro ( keys %macros ) {
846 $template =~ s/%% \s+ $macro \s+ %%/$macros{$macro}/gx;
851 # Given a code snippet, convert it to something usable in the generated file
857 $code =~ s/%1/$op1/g;
858 $code =~ s/%2/$op2/g;
867 tools/gen_operator_defs.pl - Generate the definitions for all the various
868 APL operators in all possible configurations.
872 Copyright (C) 2005-2006, The Perl Foundation.
874 This is free software; you may redistribute it and/or modify
875 it under the same terms as Parrot.
882 # cperl-indent-level: 4
885 # vim: expandtab shiftwidth=4: