1package norm
2
3import "fmt"
4
5type op string
6
7type Expr struct {
8 kind ExprKind
9
10 ident *IdentExpr
11 binary *BinExpr
12 value *ValueExpr
13}
14
15func (e Expr) String() string {
16 switch e.kind {
17 case exprKindIdent:
18 return e.ident.String()
19 case exprKindBinary:
20 return e.binary.String()
21 case exprKindValue:
22 return e.value.String()
23 }
24
25 // unreachable
26 return ""
27}
28
29func (e Expr) Binds() []any {
30 switch e.kind {
31 case exprKindIdent:
32 return e.ident.Binds()
33 case exprKindBinary:
34 return e.binary.Binds()
35 case exprKindValue:
36 return e.value.Binds()
37 }
38
39 // unreachable
40 return nil
41}
42
43type ExprKind int
44
45const (
46 exprKindIdent ExprKind = iota
47 exprKindBinary
48 exprKindValue
49)
50
51type IdentExpr string
52
53func (i IdentExpr) String() string {
54 return string(i)
55}
56
57func (i IdentExpr) Binds() []any {
58 return nil
59}
60
61func (i IdentExpr) AsExpr() Expr {
62 return Expr{
63 kind: exprKindIdent,
64 ident: &i,
65 }
66}
67
68type ValueExpr struct {
69 inner any
70}
71
72func (v ValueExpr) String() string {
73 return "?"
74}
75
76func (v ValueExpr) Binds() []any {
77 return []any{v.inner}
78}
79
80func (v ValueExpr) AsExpr() Expr {
81 return Expr{
82 kind: exprKindValue,
83 value: &v,
84 }
85}
86
87type BinExpr struct {
88 left Expr
89 op op
90 right Expr
91}
92
93func (b BinExpr) String() string {
94 return fmt.Sprintf("(%s) %s (%s)", b.left.String(), b.op, b.right.String())
95}
96
97func (b BinExpr) Binds() []any {
98 binds := b.left.Binds()
99 binds = append(binds, b.right.Binds()...)
100 return binds
101}
102
103func (b BinExpr) AsExpr() Expr {
104 return Expr{
105 kind: exprKindBinary,
106 binary: &b,
107 }
108}
109
110func buildBinExpr(left IdentExpr, op op, right any) Expr {
111 return BinExpr{left.AsExpr(), op, ValueExpr{right}.AsExpr()}.AsExpr()
112}
113func Eq(left string, right any) Expr { return buildBinExpr(IdentExpr(left), "=", right) }
114func Neq(left string, right any) Expr { return buildBinExpr(IdentExpr(left), "<>", right) }
115func Gt(left string, right any) Expr { return buildBinExpr(IdentExpr(left), ">", right) }
116func Gte(left string, right any) Expr { return buildBinExpr(IdentExpr(left), ">=", right) }
117func Lt(left string, right any) Expr { return buildBinExpr(IdentExpr(left), "<", right) }
118func Lte(left string, right any) Expr { return buildBinExpr(IdentExpr(left), "<=", right) }
119
120func (l Expr) And(r Expr) Expr { return BinExpr{l, "AND", r}.AsExpr() }
121func (l Expr) Or(r Expr) Expr { return BinExpr{l, "OR", r}.AsExpr() }