package subex import ( "main/walk" "math" "fmt" ) type valueFilter interface { valueFilter(value walk.Value) bool } type selectScalarFilter struct { scalar walk.Scalar } func (scalar selectScalarFilter) valueFilter(value walk.Value) bool { return value == scalar.scalar } type anyNumberFilter struct {} func (_ anyNumberFilter) valueFilter(value walk.Value) bool { _, isNumber := value.(walk.NumberValue) return isNumber } type anyBoolFilter struct {} func (_ anyBoolFilter) valueFilter(value walk.Value) bool { _, isBool := value.(walk.BoolValue) return isBool } type simpleValueFilter struct {} func (_ simpleValueFilter) valueFilter(value walk.Value) bool { switch value := value.(type) { case walk.NullValue: return true case walk.BoolValue: return true case walk.NumberValue: return true case walk.StringValue: return true case walk.ArrayValue: return len(value) == 0 case walk.MapValue: return len(value) == 0 default: panic("Invalid value type") } } type anyValueFilter struct {} func (_ anyValueFilter) valueFilter(value walk.Value) bool { return true } type anyArrayFilter struct {} func (_ anyArrayFilter) valueFilter(value walk.Value) bool { _, isArray := value.(walk.ArrayValue) return isArray } type anyMapFilter struct {} func (_ anyMapFilter) valueFilter(value walk.Value) bool { _, isMap := value.(walk.MapValue) return isMap } type anyStringFilter struct {} func (_ anyStringFilter) valueFilter(value walk.Value) bool { _, isString := value.(walk.StringValue) return isString } type runeFilter interface { runeFilter(r rune) bool } type anyRuneFilter struct {} func (_ anyRuneFilter) runeFilter(r rune) bool { return true } type selectRuneFilter struct { r rune } 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} }