<?php
namespace Valid;

class ArgumentException extends \Exception
{
    public function __invoke() {
        throw $this;
    }
}

class CouldBeAnyObjectForExampleLogger
{
    public function __construct($argument) {
        $this->argument = $argument;
    }
    public function __invoke() {
        // log something to file
    }
}

class Email
{
    public function __construct($email) {
        new Is(new Same($email, 'ya@ty.sobaka'), new CouldBeAnyObjectForExampleLogger($email), new ArgumentException($email));
    }
}

class Is
{
    public function __construct($expression, $do, $not) {
        $this->expression = $expression;
        $this->do = $do;
        $this->not = $not;
        
        $this();
    }
    
    public function __invoke() {
        $this->expression->__invoke() ? $this->do->__invoke() : $this->not->__invoke();
    }
    
    public function __toString() {
        throw new \TypeException(); //Can't stringify expression!
    }
}

class Same
{
    public function __construct($one, $two) {
        $this->one = $one;
        $this->two = $two;
    }
    public function __invoke() {
        return $this->one === $this->two;
    }
    public function __toString() {
        return (string)$this();
    }
}

print "first try is ok \n";

try {
    new \Valid\Email('ya@ty.sobaka');
} catch (\Exception $e) {
    print $e->getMessage() . " is not a valid login";
}

print "\nsecond try should throw exception\n";

try {
    new \Valid\Email('ya@ty.kowaka');
} catch (\Exception $e) {
    print $e->getMessage() . " is not a valid login";
}