use Red::AST::Operator; class Red::AST::Not { ... } #| Base role for unary operators role Red::AST::Unary does Red::AST::Operator { has Bool $.bind = False; method value { ... } method find-column-name { $.value.?find-column-name // Empty } method find-value { $.value.?find-value // Empty } method args { $.value } method gist { "{ $.op ~ " " if $.op.defined && $.op }{ $.value.?gist // "" }" } method new($value, Bool :$bind) { self.bless: :$value, :$bind } } #| Represents a cast operation class Red::AST::Cast does Red::AST::Unary { has Str $.type; has $.value; method gist { "($!value.gist())::$!type" } method returns { $!type } method op { "::{$!type}" }; method should-set { $!value.should-set } method new($value, $type, Bool :$bind) { self.bless: :$value, :$type, :$bind } method not { Red::AST::Not.new: self } } class Red::AST::So { ... } #| Represents a not operation class Red::AST::Not does Red::AST::Unary { has Str $.type; has $.value; has Bool $.returns; method op { "not" }; method should-set(|) { } method should-validate {} method not { Red::AST::So.new: $!value } } #| Represents a so operation class Red::AST::So does Red::AST::Unary { has Str $.type; has $.value; has Bool $.returns; method op { "" }; method should-set(|) { } method should-validate {} method not { Red::AST::Not.new: $!value } }