use v6;

use Test;

=begin pod

 Hyper operators L<S03/"Hyper operators">

=end pod

plan 265;

# L<S03/Hyper operators>
 # binary infix
my @r;
my @e;
{
        @r = (1, 2, 3) »+« (2, 4, 6);
        @e = (3, 6, 9);
        is(~@r, ~@e, "hyper-sum two arrays");

        @r = (1, 2, 3) »-« (2, 4, 6);
        @e = (-1, -2, -3);
        is(~@r, ~@e, "hyper-subtract two arrays");

        @r = (1, 2, 3) »*« (2, 4, 6);
        @e = (2, 8, 18);
        is(~@r, ~@e, "hyper-multiply two arrays");

        @r = (1, 2, 3) »x« (3, 2, 1);
        @e = ('111', '22', '3');
        is(~@r, ~@e, "hyper-x two arrays");

        @r = (1, 2, 3) »xx« (3, 2, 1);
        @e = ((1,1,1), (2,2), (3));
        is(~@r, ~@e, "hyper-xx two arrays");

        @r = (20, 40, 60) »div« (2, 5, 10);
        @e = (10, 8, 6);
        is(~@r, ~@e, "hyper-divide two arrays");

        @r = (1, 2, 3) »+« (10, 20, 30) »*« (2, 3, 4);
        @e = (21, 62, 123);
        is(~@r, ~@e, "precedence - »+« vs »*«");
}

{
        @r = (1, 2, 3) >>+<< (2, 4, 6);
        @e = (3, 6, 9);
        is(~@r, ~@e, "hyper-sum two arrays ASCII notation");

        @r = (1, 2, 3) >>-<< (2, 4, 6);
        @e = (-1, -2, -3);
        is(~@r, ~@e, "hyper-subtract two arrays ASCII notation");

        @r = (1, 2, 3) >>*<< (2, 4, 6);
        @e = (2, 8, 18);
        is(~@r, ~@e, "hyper-multiply two arrays ASCII notation");

        @r = (1, 2, 3) >>x<< (3, 2, 1);
        @e = ('111', '22', '3');
        is(~@r, ~@e, "hyper-x two arrays ASCII notation");

        @r = (1, 2, 3) >>xx<< (3, 2, 1);
        @e = ((1,1,1), (2,2), (3));
        is(~@r, ~@e, "hyper-xx two arrays ASCII notation");

        @r = (20, 40, 60) >>div<< (2, 5, 10);
        @e = (10, 8, 6);
        is(~@r, ~@e, "hyper-divide two arrays ASCII notation");

        @r = (1, 2, 3) >>+<< (10, 20, 30) >>*<< (2, 3, 4);
        @e = (21, 62, 123);
        is(~@r, ~@e, "precedence - >>+<< vs >>*<< ASCII notation");
};

{ # unary postfix
        my @r = (1, 2, 3);
        @r»++;
        my @e = (2, 3, 4);
        #?pugs todo
        is(~@r, ~@e, "hyper auto increment an array");

        @r = (1, 2, 3);
        @r>>++;
        @e = (2, 3, 4);
        #?pugs todo
        is(~@r, ~@e, "hyper auto increment an array ASCII notation");
};

{ # unary prefix
        my @r;
        @r = -« (3, 2, 1);
        my @e = (-3, -2, -1);
        is(~@r, ~@e, "hyper op on assignment/pipeline");

        @r = -<< (3, 2, 1);
        @e = (-3, -2, -1);
        is(~@r, ~@e, "hyper op on assignment/pipeline ASCII notation");
};

{ # dimension upgrade - ASCII
        my @r;
        @r = (1, 2, 3) >>+>> 1;
        my @e = (2, 3, 4);
        is(~@r, ~@e, "auto dimension upgrade on rhs ASCII notation");

        @r = 2 <<*<< (10, 20, 30);
        @e = (20, 40, 60);
        is(~@r, ~@e, "auto dimension upgrade on lhs ASCII notation");
}

{ # extension
        @r = (1,2,3,4) >>~>> <A B C D E>;
        @e = <1A 2B 3C 4D>;
        is(~@r, ~@e, "list-level element truncate on rhs ASCII notation");

        @r = (1,2,3,4,5) <<~<< <A B C D>;
        @e =  <1A 2B 3C 4D>;
        is(~@r, ~@e, "list-level element truncate on lhs ASCII notation");

        @r = (1,2,3,4) >>~>> <A B C>;
        @e = <1A 2B 3C 4A>;
        is(~@r, ~@e, "list-level element extension on rhs ASCII notation");

        @r = (1,2,3) <<~<< <A B C D>;
        @e =  <1A 2B 3C 1D>;
        is(~@r, ~@e, "list-level element extension on lhs ASCII notation");

        @r = (1,2,3,4) >>~>> <A B>;
        @e = <1A 2B 3A 4B>;
        is(~@r, ~@e, "list-level element extension on rhs ASCII notation");
        
        @r = (1,2) <<~<< <A B C D>;
        @e =  <1A 2B 1C 2D>;
        is(~@r, ~@e, "list-level element extension on lhs ASCII notation");
         
        @r = (1,2,3,4) >>~>> <A>;
        @e = <1A 2A 3A 4A>;
        is(~@r, ~@e, "list-level element extension on rhs ASCII notation");
        
        @r = (1,) <<~<< <A B C D>;
        @e = <1A 1B 1C 1D>;
        is(~@r, ~@e, "list-level element extension on lhs ASCII notation");

        @r = (1,2,3,4) >>~>> 'A';
        @e = <1A 2A 3A 4A>;
        is(~@r, ~@e, "scalar element extension on rhs ASCII notation");

        @r = 1 <<~<< <A B C D>;
        @e = <1A 1B 1C 1D>;
        is(~@r, ~@e, "scalar element extension on lhs ASCII notation");
};

{ # dimension upgrade - unicode
        @r = (1,2,3,4) »~» <A B C D E>;
        @e = <1A 2B 3C 4D>;
        is(~@r, ~@e, "list-level element truncate on rhs unicode notation");

        @r = (1,2,3,4,5) «~« <A B C D>;
        @e =  <1A 2B 3C 4D>;
        is(~@r, ~@e, "list-level element truncate on lhs unicode notation");

        @r = (1,2,3,4) »~» <A B C>;
        @e = <1A 2B 3C 4A>;
        is(~@r, ~@e, "list-level element extension on rhs unicode notation");

        @r = (1,2,3) «~« <A B C D>;
        @e =  <1A 2B 3C 1D>;
        is(~@r, ~@e, "list-level element extension on lhs unicode notation");

        @r = (1,2,3,4) »~» <A B>;
        @e = <1A 2B 3A 4B>;
        is(~@r, ~@e, "list-level element extension on rhs unicode notation");

        @r = (1,2) «~« <A B C D>;
        @e =  <1A 2B 1C 2D>;
        is(~@r, ~@e, "list-level element extension on lhs unicode notation");
 
        @r = (1,2,3,4) »~» <A>;
        @e = <1A 2A 3A 4A>;
        is(~@r, ~@e, "list-level element extension on rhs unicode notation");

        @r = (1,) «~« <A B C D>;
        @e = <1A 1B 1C 1D>;
        is(~@r, ~@e, "list-level element extension on lhs unicode notation");

        @r = (1,2,3,4) »~» 'A';
        @e = <1A 2A 3A 4A>;
        is(~@r, ~@e, "scalar element extension on rhs unicode notation");

        @r = 1 «~« <A B C D>;
        @e = <1A 1B 1C 1D>;
        is(~@r, ~@e, "scalar element extension on lhs unicode notation");
};

{ # unary postfix with integers
        my @r;
        @r = (1, 4, 9)».sqrt;
        my @e = (1, 2, 3);
        is(~@r, ~@e, "method call on integer list elements");

        @r = (1, 4, 9)>>.sqrt;
        @e = (1, 2, 3);
        is(~@r, ~@e, "method call on integer list elements (ASCII)");
}

#?rakudo skip '@array»++'
{
        my (@r, @e);
        (@r = (1, 4, 9))»++;
        @e = (2, 5, 10);
        is(~@r, ~@e, "operator call on integer list elements");

        (@r = (1, 4, 9)).»++;
        is(~@r, ~@e, "operator call on integer list elements (Same thing, dot form)");

        (@r = (1, 4, 9))».++;
        @e = (2, 5, 9);
        is(~@r, ~@e, "operator call on integer list elements (Same thing, dot form)");

        (@r = (1, 4, 9)).».++;
        is(~@r, ~@e, "operator call on integer list elements (Same thing, dot form)");

        (@r = (1, 4, 9))\  .»\  .++;
        @e = (2, 5, 9);
        is(~@r, ~@e, "operator call on integer list elements (Same thing, upspace form)");
};

{ # unary postfix again, but with a twist
        my @r;
        eval '@r = ("f", "oo", "bar")».chars';
        my @e = (1, 2, 3);
        is(~@r, ~@e, "method call on list elements");

        eval '@r = ("f", "oo", "bar").».chars';
        @e = (1, 2, 3);
        is(~@r, ~@e, "method call on list elements (Same thing, dot form)");


        eval '@r = ("f", "oo", "bar")>>.chars';
        @e = (1, 2, 3);
        is(~@r, ~@e, "method call on list elements (ASCII)");

        eval '@r = ("f", "oo", "bar").>>.chars';