-
Notifications
You must be signed in to change notification settings - Fork 221
/
Copy pathfilter.go
89 lines (78 loc) · 3.3 KB
/
filter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// ================================================================
// This handles bare booleans and filter statements.
//
// Example of the former: 'NR > 10' or '$x =~ "(..)_(...)"' without if or '{...}' body.
//
// Example of the latter: mlr put 'filter NR > 10'.
//
// For mlr put, these are no-ops except side-effects (like regex-captures).
// (Unless the user uses the filter keyword, like mlr put 'filter NR < 10'.)
//
// For mlr filter, they set the filter condition.
//
// For mlr repl, they become the expression to be printed after evaluation --
// e.g. if the user types '1+2' then the repl prints '3' and that expression is
// stored as a bare-boolean evaluable. Which is a misnomer (sorry!) since 3 is
// not a boolean.
// ================================================================
package cst
import (
"github.com/johnkerl/miller/v6/pkg/dsl"
"github.com/johnkerl/miller/v6/pkg/lib"
"github.com/johnkerl/miller/v6/pkg/runtime"
)
// ----------------------------------------------------------------
// BareBooleanStatementNode is for implicit filter statements such as mlr
// filter 'NR < 10' -- "implicit" since the word "filter" doesn't appear within
// the single quotes as part of the DSL expression per se. Or (as noted above)
// mlr put 'NR < 10' is a no-op.
type BareBooleanStatementNode struct {
bareBooleanEvaluable IEvaluable
writeToState bool
}
// ----------------------------------------------------------------
func (root *RootNode) BuildBareBooleanStatementNode(astNode *dsl.ASTNode) (IExecutable, error) {
lib.InternalCodingErrorIf(astNode.Type != dsl.NodeTypeBareBoolean)
lib.InternalCodingErrorIf(len(astNode.Children) != 1)
bareBooleanEvaluable, err := root.BuildEvaluableNode(astNode.Children[0])
if err != nil {
return nil, err
}
return &BareBooleanStatementNode{
bareBooleanEvaluable: bareBooleanEvaluable,
writeToState: root.dslInstanceType != DSLInstanceTypePut,
}, nil
}
func (node *BareBooleanStatementNode) Execute(state *runtime.State) (*BlockExitPayload, error) {
// Evaluate always -- along with any side effects such as regex captures
// from things like '$x =~ "(..)_(...)"' -- but for mlr put do not store
// the result as state.FilterExpression. (For mlr put, bare booleans are
// no-ops, outside of any side effects they may have.)
result := node.bareBooleanEvaluable.Evaluate(state)
if node.writeToState {
state.FilterExpression = result
}
return nil, nil
}
// ----------------------------------------------------------------
// FilterStatementNode is for explicit filter statements such as mlr put
// 'filter NR < 10', where the word "filter" appears within the single quotes
// and is part of the DSL expression per se.
type FilterStatementNode struct {
filterEvaluable IEvaluable
}
func (root *RootNode) BuildFilterStatementNode(astNode *dsl.ASTNode) (IExecutable, error) {
lib.InternalCodingErrorIf(astNode.Type != dsl.NodeTypeFilterStatement)
lib.InternalCodingErrorIf(len(astNode.Children) != 1)
filterEvaluable, err := root.BuildEvaluableNode(astNode.Children[0])
if err != nil {
return nil, err
}
return &FilterStatementNode{
filterEvaluable: filterEvaluable,
}, nil
}
func (node *FilterStatementNode) Execute(state *runtime.State) (*BlockExitPayload, error) {
state.FilterExpression = node.filterEvaluable.Evaluate(state).Copy()
return nil, nil
}