func Walk(v Visitor, node Node) {
	if v = v.Visit(node); v == nil {
		return
	}
	switch n := node.(type) {
	case *BinaryExpr:
		Walk(v, n.LHS)
		Walk(v, n.RHS)
	case *ParenExpr:
		Walk(v, n.Expr)
	}
}
Walk traverses a node hierarchy in depth-first order.
package conditions
import (
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"
)
type DataType string
const (
	Unknown  = DataType("")
	Number   = DataType("number")
	Boolean  = DataType("boolean")
	String   = DataType("string")
	Time     = DataType("time")
	Duration = DataType("duration")
)
func InspectDataType(v interface{}) DataType {
	switch v.(type) {
	case float64:
		return Number
	case bool:
		return Boolean
	case string:
		return String
	case time.Time:
		return Time
	case time.Duration:
		return Duration
	default:
		return Unknown
	}
}
type Node interface {
	node()
	String() string
}
func (_ *VarRef) node()             {}
func (_ *NumberLiteral) node()      {}
func (_ *StringLiteral) node()      {}
func (_ *BooleanLiteral) node()     {}
func (_ *TimeLiteral) node()        {}
func (_ *DurationLiteral) node()    {}
func (_ *BinaryExpr) node()         {}
func (_ *ParenExpr) node()          {}
func (_ *SliceStringLiteral) node() {}
func (_ *SliceNumberLiteral) node() {}
type Expr interface {
	Node
	expr()
	Args() []string
}
func (_ *VarRef) expr()             {}
func (_ *NumberLiteral) expr()      {}
func (_ *StringLiteral) expr()      {}
func (_ *BooleanLiteral) expr()     {}
func (_ *TimeLiteral) expr()        {}
func (_ *DurationLiteral) expr()    {}
func (_ *BinaryExpr) expr()         {}
func (_ *ParenExpr) expr()          {}
func (_ *SliceStringLiteral) expr() {}
func (_ *SliceNumberLiteral) expr() {}
type VarRef struct {
	Val string
}
func (r *VarRef) String() string { return QuoteIdent(r.Val) }
func (r *VarRef) Args() []string {
	return []string{r.Val}
}
type NumberLiteral struct {
	Val float64
}
func (l *NumberLiteral) String() string { return strconv.FormatFloat(l.Val, 'f', 3, 64) }
func (n *NumberLiteral) Args() []string {
	args := []string{}
	return args
}
func NewSliceStringLiteral(val []string) *SliceStringLiteral {
	ssl := &SliceStringLiteral{}
	ssl.Val = val
	ssl.m = make(map[string]struct{})
	for _, item := range ssl.Val {
		ssl.m[item] = struct{}{}
	}
	return ssl
}
type SliceStringLiteral struct {
	Val []string
	m   map[string]struct{}
}
func (l *SliceStringLiteral) String() string {
	return fmt.Sprintf("%s", l.Val)
}
func (l *SliceStringLiteral) Args() []string {
	args := []string{}
	return args
}
type SliceNumberLiteral struct {
	Val []float64
}
func (l *SliceNumberLiteral) String() string {
	return fmt.Sprintf("%v", l.Val)
}
func (l *SliceNumberLiteral) Args() []string {
	args := []string{}
	return args
}
type BooleanLiteral struct {
	Val bool
}
func (l *BooleanLiteral) String() string {
	if l.Val {
		return "true"
	}
	return "false"
}
func (l *BooleanLiteral) Args() []string {
	args := []string{}
	return args
}
type StringLiteral struct {
	Val string
}
func (l *StringLiteral) String() string { return Quote(l.Val) }
type TimeLiteral struct {
	Val time.Time
}
func (l *StringLiteral) Args() []string {
	args := []string{}
	return args
}
func (l *TimeLiteral) String() string { return l.Val.UTC().Format("2006-01-02 15:04:05.999") }
type DurationLiteral struct {
	Val time.Duration
}
func (l *DurationLiteral) String() string { return FormatDuration(l.Val) }
type BinaryExpr struct {
	Op  Token
	LHS Expr
	RHS Expr
}
func (e *BinaryExpr) String() string {
	return fmt.Sprintf("%s %s %s", e.LHS.String(), e.Op, e.RHS.String())
}
func (e *BinaryExpr) Args() []string {
	args := []string{}
	args = append(e.LHS.Args(), args...)
	args = append(e.RHS.Args(), args...)
	return args
}
type ParenExpr struct {
	Expr Expr
}
func (e *ParenExpr) String() string { return fmt.Sprintf("(%s)", e.Expr.String()) }
func (p *ParenExpr) Args() []string {
	args := []string{}
	args = append(p.Expr.Args(), args...)
	return args
}
type Visitor interface {
	Visit(Node) Visitor
}