File: state.go

package info (click to toggle)
miller 6.16.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 87,928 kB
  • sloc: ruby: 162; sh: 119; makefile: 87
file content (95 lines) | stat: -rw-r--r-- 2,977 bytes parent folder | download
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
90
91
92
93
94
95
// ================================================================
// Tracks everything needed for statement evaluation/assignment in the Miller
// DSL runtimne: current record/context (the latter being NF, NR, etc);
// out-of-stream variables; local-variable stack; etc.
// ================================================================

package runtime

import (
	"container/list"

	"github.com/johnkerl/miller/v6/pkg/cli"
	"github.com/johnkerl/miller/v6/pkg/lib"
	"github.com/johnkerl/miller/v6/pkg/mlrval"
	"github.com/johnkerl/miller/v6/pkg/types"
)

type State struct {
	Inrec                    *mlrval.Mlrmap
	Context                  *types.Context
	Oosvars                  *mlrval.Mlrmap
	FilterExpression         *mlrval.Mlrval
	Stack                    *Stack
	OutputRecordsAndContexts *list.List // list of *types.RecordAndContext

	// For holding "\0".."\9" between where they are set via things like
	// '$x =~ "(..)_(...)"', and interpolated via things like '$y = "\2:\1"'.
	//
	// Each top-level block and user-defined function has its own captures.
	//
	// For example, in function `f()`, one can do `somevar =~ someregex`, then
	// call some function `g()` which also uses `=~`, and then when `g()` returns,
	// `f()` will have its "\1", "\2", etc intact.
	//
	// This is necessary for the stateful semantics of `=~` and "\1", "\2", etc.
	// Those are avoided when the user calls `matchx`, which is newer, and
	// stateless. However, `=~` exists in the Miller DSL and we must support it.
	regexCapturesByFrame [][]string

	Options *cli.TOptions

	// StrictMode allows for runtime handling of absent-reads and untyped assignments.
	StrictMode bool
}

func NewEmptyState(options *cli.TOptions, strictMode bool) *State {

	// See lib.MakeEmptyCaptures for context.
	regexCapturesByFrame := make([][]string, 1)
	regexCapturesByFrame[0] = lib.MakeEmptyCaptures()

	oosvars := mlrval.NewMlrmap()
	return &State{
		Inrec:                nil,
		Context:              nil,
		Oosvars:              oosvars,
		FilterExpression:     mlrval.TRUE,
		Stack:                NewStack(),
		regexCapturesByFrame: regexCapturesByFrame,

		// OutputRecordsAndContexts is assigned after construction

		Options: options,

		StrictMode: strictMode,
	}
}

func (state *State) Update(
	inrec *mlrval.Mlrmap,
	context *types.Context,
) {
	state.Inrec = inrec
	state.Context = context
	state.regexCapturesByFrame[0] = lib.MakeEmptyCaptures()
}

func (state *State) SetRegexCaptures(
	captures []string,
) {
	state.regexCapturesByFrame[0] = lib.CopyStringArray(captures)
}

func (state *State) GetRegexCaptures() []string {
	regexCaptures := state.regexCapturesByFrame[0]
	return lib.CopyStringArray(regexCaptures)
}

func (state *State) PushRegexCapturesFrame() {
	state.regexCapturesByFrame = append([][]string{lib.MakeEmptyCaptures()}, state.regexCapturesByFrame...)
}

func (state *State) PopRegexCapturesFrame() {
	state.regexCapturesByFrame = state.regexCapturesByFrame[1:]
}