diff options
Diffstat (limited to 'subex/filter.go')
| -rw-r--r-- | subex/filter.go | 171 | 
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} +} | 
