RaCoCo result: Red::AST::Infixes

# Red::AST::Infixes 35.9%

    use Red::AST::Infix;
    use Red::AST::Value;
    class Red::AST::Sum     { ... }
    class Red::AST::Eq      { ... }
    class Red::AST::Ne      { ... }
    class Red::AST::Lt      { ... }
    class Red::AST::Gt      { ... }
    class Red::AST::Le      { ... }
    class Red::AST::Ge      { ... }
    class Red::AST::AND     { ... }
    class Red::AST::OR      { ... }
    class Red::AST::Mul     { ... }
    class Red::AST::Div     { ... }
    class Red::AST::IDiv    { ... }
    class Red::AST::Mod     { ... }
    class Red::AST::Concat  { ... }
    class Red::AST::Like    { ... }
    class Red::AST::In      { ... }

    #| Represents a sum operation
    class Red::AST::Sum does Red::AST::Infix {
        has $.op = "+";
        has $.returns = (self.left | self.right).returns ~~ Num ?? Num !! Int;

        method should-set(--> Hash()) {
            self.find-column-name => self.find-value
        }

        method should-validate {}

        method find-column-name {
            gather for self.args {
                .take for .?find-column-name
            }
        }

        method find-value {
            for self.args {
                .return with .?find-value
            }
        }
    }

    #| Represents a subtraction operation
    class Red::AST::Sub does Red::AST::Infix {
        has $.op = "-";
        has $.returns = (self.left | self.right).returns ~~ Num ?? Num !! Int;

        method should-set(--> Hash()) {
            self.find-column-name => self.find-value
        }

        method should-validate {}

        method find-column-name {
            gather for self.args {
                .take for .?find-column-name
            }
        }

        method find-value {
            for self.args {
                .return with .?find-value
            }
        }
    }

    #| Represents a equality operation
    class Red::AST::Eq does Red::AST::Infix {
        has $.op = "=";
        has Bool $.returns;

        method should-set(--> Hash()) {
            self.find-column-name => self.find-value
        }

        method should-validate {}

        method find-column-name {
            gather for self.args {
                .take if .defined for .?find-column-name
            }
        }

        method find-value {
            for self.args {
                .return with .?find-value
            }
        }

        method not {
            Red::AST::Ne.new: $.left, $.right, :bind-left($.bind-left), :bind-right($.bind-right)
        }
    }

    #| Represents a not equality operation
    class Red::AST::Ne does Red::AST::Infix {
        has $.op = "!=";
        has Bool $.returns;

        method should-set(--> Hash()) { }

        method should-validate {}

        method not {
            Red::AST::Eq.new: $.left, $.right, :bind-left($.bind-left), :bind-right($.bind-right)
        }
    }

    #| Represents a less than operation
    class Red::AST::Lt does Red::AST::Infix {
        has $.op = "<";
        has Bool $.returns;
        method should-set(--> Hash()) { }
        method should-validate {}

        method not {
            Red::AST::Ge.new: $.left, $.right, :bind-left($.bind-left), :bind-right($.bind-right)
        }
    }

    #| Represents a greater than operation
    class Red::AST::Gt does Red::AST::Infix {
        has $.op = ">";
        has Bool $.returns;
        method should-set(--> Hash()) { }
        method should-validate {}

        method not {
            Red::AST::Le.new: $.left, $.right, :bind-left($.bind-left), :bind-right($.bind-right)
        }
    }

    #| Represents a less than equal operation
    class Red::AST::Le does Red::AST::Infix {
        has $.op = "<=";
        has Bool $.returns;
        method should-set(--> Hash()) { }
        method should-validate {}

        method not {
            Red::AST::Gt.new: $.left, $.right, :bind-left($.bind-left), :bind-right($.bind-right)
        }
    }

    #| Represents a greater then equal operation
    class Red::AST::Ge does Red::AST::Infix {
        has $.op = ">=";
        has Bool $.returns;
        method should-set(--> Hash()) { }
        method should-validate {}

        method not {
            Red::AST::Lt.new: $.left, $.right, :bind-left($.bind-left), :bind-right($.bind-right)
        }
    }

    #| Represents a AND operation
    class Red::AST::AND does Red::AST::Infix {
        #also does Red::AST::Optimizer::And;

        has $.op = "AND";
        has Bool $.returns;

        multi method new(Red::AST $left is copy, Red::AST $right is copy) {
            my \ret = self.optimize: $left, $right;
            return ret if ret.DEFINITE && ret !~~ Empty;

            $left  .= value if $left  ~~ Red::AST::So;
            $right .= value if $right ~~ Red::AST::So;

            return $left if $left eqv $right;
            return ast-value(False) if $left eqv $right.not;

            self.WHAT.bless: :$left, :$right
        }

        method should-set(--> Hash()) {
            [$.left, $.right].flatmap({ .should-set })
        }

        method should-validate {}

        method not {
            Red::AST::OR.new: $.left.not, $.right.not, :bind-left($.bind-left), :bind-right($.bind-right)
        }
    }

    #| Represents a OR operation
    class Red::AST::OR does Red::AST::Infix {
        #also does Red::AST::Optimizer::OR;
        has $.op = "OR";
        has Bool $.returns;

        multi method new(Red::AST $left is copy, Red::AST $right is copy) {
            my \ret = self.optimize: $left, $right;
            return ret if ret.DEFINITE && ret !~~ Empty;

            $left  .= value if $left  ~~ Red::AST::So;
            $right .= value if $right ~~ Red::AST::So;

            return $left if $left eqv $right;
            return ast-value(True) if $left eqv $right.not;

            self.WHAT.bless: :$left, :$right
        }

        method should-set(--> Hash()) {}

        method should-validate {}

        method not {
            Red::AST::AND.new: $.left.not, $.right.not, :bind-left($.bind-left), :bind-right($.bind-right)
        }
    }

    #| Represents a multiplication operation
    class Red::AST::Mul does Red::AST::Infix {
        has $.op = "*";
        has $.returns = (self.left | self.right).returns ~~ Num ?? Num !! Int;

        method should-set(--> Hash()) {
            self.find-column-name => self.find-value
        }

        method should-validate {}

        method find-column-name {
            gather for self.args {
                .take for .?find-column-name
            }
        }

        method find-value {
            for self.args {
                .return with .?find-value
            }
        }
    }

    #| Represents a division operation
    class Red::AST::Div does Red::AST::Infix {
        has $.op = "/";
        has Num $.returns;

        method should-set(--> Hash()) {
            self.find-column-name => self.find-value
        }

        method should-validate {}

        method find-column-name {
            gather for self.args {
                .take for .?find-column-name
            }
        }

        method find-value {
            for self.args {
                .return with .?find-value
            }
        }
    }

    #| Represents a division operation
    class Red::AST::IDiv does Red::AST::Infix {
        has $.op = "/";
        has Int $.returns;

        method should-set(--> Hash()) {
            self.find-column-name => self.find-value
        }

        method should-validate {}

        method find-column-name {
            gather for self.args {
                .take for .?find-column-name
            }
        }

        method find-value {
            for self.args {
                .return with .?find-value
            }
        }
    }

    #| Represents a module operation
    class Red::AST::Mod does Red::AST::Infix {
        has $.op = "%";
        has Int $.returns;

        method should-set(--> Hash()) {
            self.find-column-name => self.find-value
        }

        method should-validate {}

        method find-column-name {
            gather for self.args {
                .take for .?find-column-name
            }
        }

        method find-value {
            for self.args {
                .return with .?find-value
            }
        }
    }

    #| Represents a concatenation operation
    class Red::AST::Concat does Red::AST::Infix {
        has $.op = "||";
        has Str $.returns;

        method should-set(--> Hash()) {}

        method should-validate {}

        multi method new(Red::AST $left, Red::AST::Value $ where .value eq "",  *%) { $left }
        multi method new(Red::AST::Value $ where .value eq "", Red::AST $right, *%) { $right }
    }

    #| Represents a like operation
    class Red::AST::Like does Red::AST::Infix {
        has $.op = "like";
        has Str $.returns;

        method should-set(--> Hash()) {}

        method should-validate {}

        multi method new(Red::AST $left, Red::AST::Value $ where .value eq "",  *%) { $left }
    }

    #| Represents a not in operation
    class Red::AST::NotIn does Red::AST::Infix {
        has $.op = "NOT IN";
        has Str $.returns;

        method should-set(--> Hash()) {}

        method should-validate {}

        method not {
            Red::AST::In.new: $!left, $!right;
        }
    }

    #| Represents a in operation
    class Red::AST::In does Red::AST::Infix {
        has $.op = "IN";
        has Str $.returns;

        method should-set(--> Hash()) {}

        method should-validate {}

        method not {
            Red::AST::NotIn.new: $!left, $!right;
        }
    }