<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/subex/filter.go
diff options
context:
space:
mode:
Diffstat (limited to 'subex/filter.go')
-rw-r--r--subex/filter.go171
1 files changed, 171 insertions, 0 deletions
diff --git a/subex/filter.go b/subex/filter.go
index 309d6c7..87c83a4 100644
--- a/subex/filter.go
+++ b/subex/filter.go
@@ -2,6 +2,8 @@ package subex
import (
"main/walk"
+ "math"
+ "fmt"
)
type valueFilter interface {
@@ -86,3 +88,172 @@ type selectRuneFilter struct {
func (f selectRuneFilter) runeFilter(r rune) bool {
return f.r == r
}
+
+type numberFilter interface {
+ add(m float64) numberFilter
+ multiply(m float64) numberFilter
+ numberFilter(n float64) bool
+}
+
+func (_ anyNumberFilter) numberFilter(n float64) bool {
+ return true
+}
+func (_ anyNumberFilter) add(m float64) numberFilter {
+ return anyNumberFilter{}
+}
+func (_ anyNumberFilter) multiply(m float64) numberFilter {
+ if m == 0.0 {
+ return equalNumberFilter {0.0}
+ } else {
+ return anyNumberFilter{}
+ }
+}
+func (_ anyNumberFilter) String() string {
+ return "r"
+}
+
+type divisibleNumberFilter struct {
+ divisor float64
+ target float64
+}
+func (d divisibleNumberFilter) numberFilter(n float64) bool {
+ mod := math.Mod(n, d.divisor)
+ if mod < 0 {
+ mod += d.divisor
+ }
+ return mod == d.target
+}
+func (d divisibleNumberFilter) add(m float64) numberFilter {
+ mod := math.Mod(m + d.target, d.divisor)
+ if mod < 0 {
+ mod += d.divisor
+ }
+ return divisibleNumberFilter {
+ divisor: d.divisor,
+ target: mod,
+ }
+}
+func (d divisibleNumberFilter) multiply(m float64) numberFilter {
+ if m == 0.0 {
+ return equalNumberFilter {0.0}
+ }
+
+ target := d.target
+ if m < 0 {
+ target = d.divisor - target
+ m = -m
+ }
+
+ return divisibleNumberFilter {
+ divisor: d.divisor * m,
+ target: target * m,
+ }
+}
+func (d divisibleNumberFilter) String() string {
+ return fmt.Sprintf("(x %% %v == %v)", d.divisor, d.target)
+}
+
+type andNumberFilter struct {
+ lhs, rhs numberFilter
+}
+func (a andNumberFilter) numberFilter(n float64) bool {
+ return a.lhs.numberFilter(n) && a.rhs.numberFilter(n)
+}
+func (a andNumberFilter) add(m float64) numberFilter {
+ return andNumberFilter {
+ lhs: a.lhs.add(m),
+ rhs: a.rhs.add(m),
+ }
+}
+func (a andNumberFilter) multiply(m float64) numberFilter {
+ return andNumberFilter {
+ lhs: a.lhs.multiply(m),
+ rhs: a.rhs.multiply(m),
+ }
+}
+func (a andNumberFilter) String() string {
+ return fmt.Sprintf("(%v && %v)", a.lhs, a.rhs)
+}
+
+type orNumberFilter struct {
+ lhs, rhs numberFilter
+}
+func (o orNumberFilter) numberFilter(n float64) bool {
+ return o.lhs.numberFilter(n) || o.rhs.numberFilter(n)
+}
+func (o orNumberFilter) String() string {
+ return fmt.Sprintf("(%v || %v)", o.lhs, o.rhs)
+}
+
+type notNumberFilter struct {
+ operand numberFilter
+}
+func (no notNumberFilter) numberFilter(n float64) bool {
+ return !no.operand.numberFilter(n)
+}
+func (no notNumberFilter) add(m float64) numberFilter {
+ return notNumberFilter {no.operand.add(m)}
+}
+func (no notNumberFilter) multiply(m float64) numberFilter {
+ return notNumberFilter {no.operand.multiply(m)}
+}
+func (no notNumberFilter) String() string {
+ return fmt.Sprintf("(!%v)", no.operand)
+}
+
+type lessThanNumberFilter struct {
+ rhs float64
+}
+func (l lessThanNumberFilter) numberFilter(n float64) bool {
+ return n < l.rhs
+}
+func (l lessThanNumberFilter) add(m float64) numberFilter {
+ return lessThanNumberFilter {l.rhs + m}
+}
+func (l lessThanNumberFilter) multiply(m float64) numberFilter {
+ if m > 0 {
+ return lessThanNumberFilter {l.rhs * m}
+ } else if m < 0 {
+ return greaterThanNumberFilter {l.rhs * m}
+ } else {
+ return equalNumberFilter {0}
+ }
+}
+func (l lessThanNumberFilter) String() string {
+ return fmt.Sprintf("(x < %v)", l.rhs)
+}
+
+type greaterThanNumberFilter struct {
+ rhs float64
+}
+func (g greaterThanNumberFilter) numberFilter(n float64) bool {
+ return n > g.rhs
+}
+func (g greaterThanNumberFilter) add(m float64) numberFilter {
+ return greaterThanNumberFilter {g.rhs + m}
+}
+func (g greaterThanNumberFilter) multiply(m float64) numberFilter {
+ if m > 0 {
+ return greaterThanNumberFilter {g.rhs * m}
+ } else if m < 0 {
+ return lessThanNumberFilter {g.rhs * m}
+ } else {
+ return equalNumberFilter {0}
+ }
+}
+func (g greaterThanNumberFilter) String() string {
+ return fmt.Sprintf("(x > %v)", g.rhs)
+}
+
+type equalNumberFilter struct {
+ rhs float64
+}
+func (e equalNumberFilter) numberFilter(n float64) bool {
+ return n == e.rhs
+}
+func (e equalNumberFilter) add(m float64) numberFilter {
+ return equalNumberFilter {e.rhs + m}
+}
+func (e equalNumberFilter) multiply(m float64) numberFilter {
+ return equalNumberFilter {e.rhs * m}
+}