use v6-alpha;

use Test;

plan 9*2;

# L<S06/"Operator overloading">
# Later, we want to run the same tests with two classes, Foo and Bar.
# Foo overloads the operators by using multi methods, Bar by using multi subs.
# But as currently both Foo and Bar do not compile, we have to create a
# stubclass, which is then given to &run_tests_with.
# But if the class does compile, $foo_class and $bar_class will be set to the
# correct classes (Foo and Bar), and the tests have a chance to succeed.
class StubClass {}
my ($foo_class, $bar_class) = (StubClass, StubClass);

eval '
    class Foo {
    has $.bar is rw;
    multi method prefix:<~> ($self)  { return $.bar }
    mutli method infix:<+>  ($a, $b) { return "$a $b" }
    }

    $foo_class = Foo;
';

eval '
    class Bar {
    has $.bar is rw;
    }

    multi sub prefix:<~> (Bar $self)      { return $self.bar }
    mutli sub infix:<+>  (Bar $a, Bar $b) { return "$a $b" }

    $bar_class = Bar;
';

run_tests_with($foo_class);
run_tests_with($bar_class);

sub run_tests_with($class) {
    {
    my $val;
    lives_ok {
        my $foo = $class.new();
        $foo.bar = 'software';
        $val = "$foo"
    }, '... class methods work for class', :todo<feature>;
    is($val, 'software', '... basic prefix operator overloading worked', :todo<feature>);

    lives_ok {
        my $foo = $class.new();
        $foo.bar = 'software';
        $val = $foo + $foo;
    }, '... class methods work for class', :todo<feature>;
    is($val, 'software software', '... basic infix operator overloading worked', :todo<feature>);
    }

    # Test that the object is correctly stringified when it is in an array.
    # And test that »...« automagically work, too.
    {
      my $obj;
      lives_ok {
      $obj     = $class.new;
      $obj.bar = "pugs";
      }, "instantiating a class which defines operators worked", :todo<feature>;

      my @foo = ($obj, $obj, $obj);
      my $res;
      lives_ok { $res = ~@foo }, "stringification didn't die", :todo<feature>;
      is $res, "pugs pugs pugs", "stringification overloading worked in array stringification", :todo<feature>;

      lives_ok { $res = ~[@foo »~« "!"] }, "stringification with hyperization didn't die", :todo<feature>;
      is $res, "pugs! pugs! pugs!", "stringification overloading was hyperized correctly", :todo<feature>;
    }
}
