This commit is contained in:
John Kerl 2026-02-01 15:44:08 -05:00 committed by GitHub
parent ced5e43065
commit 143ff7e20d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 6 additions and 473 deletions

View file

@ -46,16 +46,6 @@ type AssignmentNode struct {
rvalueNode IEvaluable
}
func NewAssignmentNode(
lvalueNode IAssignable,
rvalueNode IEvaluable,
) *AssignmentNode {
return &AssignmentNode{
lvalueNode: lvalueNode,
rvalueNode: rvalueNode,
}
}
func (node *AssignmentNode) Execute(
state *runtime.State,
) (*BlockExitPayload, error) {
@ -96,14 +86,6 @@ type UnsetNode struct {
lvalueNodes []IAssignable
}
func NewUnsetNode(
lvalueNodes []IAssignable,
) *UnsetNode {
return &UnsetNode{
lvalueNodes: lvalueNodes,
}
}
func (node *UnsetNode) Execute(state *runtime.State) (*BlockExitPayload, error) {
for _, lvalueNode := range node.lvalueNodes {
lvalueNode.Unassign(state)

View file

@ -2723,19 +2723,6 @@ func (manager *BuiltinFunctionManager) showSingleUsage(
}
}
func (manager *BuiltinFunctionManager) ListBuiltinFunctionUsageApproximate(
text string,
) bool {
found := false
for _, builtinFunctionInfo := range *manager.lookupTable {
if strings.Contains(builtinFunctionInfo.name, text) {
fmt.Printf(" %s\n", builtinFunctionInfo.name)
found = true
}
}
return found
}
func describeNargs(info *BuiltinFunctionInfo) string {
if info.hasMultipleArities {
pieces := make([]string, 0)

View file

@ -934,55 +934,6 @@ func (root *RootNode) BuildIndexedLvalueNode(astNode *dsl.ASTNode) (IAssignable,
return NewIndexedLvalueNode(baseLvalue, indexEvaluables), nil
}
// BuildDottedLvalueNode is basically the same as BuildIndexedLvalueNode except
// at the syntax level:
// 'mymap["x"]["y"]' is the same as 'mymap.x.y'.
func (root *RootNode) BuildDottedLvalueNode(astNode *dsl.ASTNode) (IAssignable, error) {
lib.InternalCodingErrorIf(astNode.Type != dsl.NodeTypeDotOperator)
lib.InternalCodingErrorIf(astNode == nil)
var baseLvalue IAssignable = nil
indexEvaluables := make([]IEvaluable, 0)
var err error = nil
// $ mlr -n put -v '$x.a.b=3'
// DSL EXPRESSION:
// $x.a.b=3
// AST:
// * statement block
// * assignment "="
// * dot operator "."
// * dot operator "."
// * direct field value "x"
// * local variable "a"
// * local variable "b"
// * int literal "3"
// In the AST, the indices come in last-shallowest, down to first-deepest,
// then the base Lvalue.
walkerNode := astNode
for {
if walkerNode.Type == dsl.NodeTypeDotOperator {
lib.InternalCodingErrorIf(walkerNode == nil)
lib.InternalCodingErrorIf(len(walkerNode.Children) != 2)
indexEvaluable, err := root.BuildEvaluableNode(walkerNode.Children[1])
walkerNode.Children[1].Print()
if err != nil {
return nil, err
}
indexEvaluables = append([]IEvaluable{indexEvaluable}, indexEvaluables...)
walkerNode = walkerNode.Children[0]
} else {
baseLvalue, err = root.BuildAssignableNode(walkerNode)
if err != nil {
return nil, err
}
break
}
}
return NewIndexedLvalueNode(baseLvalue, indexEvaluables), nil
}
func NewIndexedLvalueNode(
baseLvalue IAssignable,
indexEvaluables []IEvaluable,

View file

@ -7,9 +7,6 @@ package csv
import (
"bufio"
"io"
"strings"
"unicode"
"unicode/utf8"
)
// A Writer writes records using CSV encoding.
@ -40,142 +37,3 @@ func NewWriter(w io.Writer) *Writer {
w: bufio.NewWriter(w),
}
}
// Write writes a single CSV record to w along with any necessary quoting.
// A record is a slice of strings with each string being one field.
// Writes are buffered, so Flush must eventually be called to ensure
// that the record is written to the underlying io.Writer.
func (w *Writer) Write(record []string) error {
if !validDelim(w.Comma) {
return errInvalidDelim
}
for n, field := range record {
if n > 0 {
if _, err := w.w.WriteRune(w.Comma); err != nil {
return err
}
}
// If we don't have to have a quoted field then just
// write out the field and continue to the next field.
if !w.fieldNeedsQuotes(field) {
if _, err := w.w.WriteString(field); err != nil {
return err
}
continue
}
if err := w.w.WriteByte('"'); err != nil {
return err
}
for len(field) > 0 {
// Search for special characters.
i := strings.IndexAny(field, "\"\r\n")
if i < 0 {
i = len(field)
}
// Copy verbatim everything before the special character.
if _, err := w.w.WriteString(field[:i]); err != nil {
return err
}
field = field[i:]
// Encode the special character.
if len(field) > 0 {
var err error
switch field[0] {
case '"':
_, err = w.w.WriteString(`""`)
case '\r':
if !w.UseCRLF {
err = w.w.WriteByte('\r')
}
case '\n':
if w.UseCRLF {
_, err = w.w.WriteString("\r\n")
} else {
err = w.w.WriteByte('\n')
}
}
field = field[1:]
if err != nil {
return err
}
}
}
if err := w.w.WriteByte('"'); err != nil {
return err
}
}
var err error
if w.UseCRLF {
_, err = w.w.WriteString("\r\n")
} else {
err = w.w.WriteByte('\n')
}
return err
}
// Flush writes any buffered data to the underlying io.Writer.
// To check if an error occurred during the Flush, call Error.
func (w *Writer) Flush() {
w.w.Flush()
}
// Error reports any error that has occurred during a previous Write or Flush.
func (w *Writer) Error() error {
_, err := w.w.Write(nil)
return err
}
// WriteAll writes multiple CSV records to w using Write and then calls Flush,
// returning any error from the Flush.
func (w *Writer) WriteAll(records [][]string) error {
for _, record := range records {
err := w.Write(record)
if err != nil {
return err
}
}
return w.w.Flush()
}
// fieldNeedsQuotes reports whether our field must be enclosed in quotes.
// Fields with a Comma, fields with a quote or newline, and
// fields which start with a space must be enclosed in quotes.
// We used to quote empty strings, but we do not anymore (as of Go 1.4).
// The two representations should be equivalent, but Postgres distinguishes
// quoted vs non-quoted empty string during database imports, and it has
// an option to force the quoted behavior for non-quoted CSV but it has
// no option to force the non-quoted behavior for quoted CSV, making
// CSV with quoted empty strings strictly less useful.
// Not quoting the empty string also makes this package match the behavior
// of Microsoft Excel and Google Drive.
// For Postgres, quote the data terminating string `\.`.
func (w *Writer) fieldNeedsQuotes(field string) bool {
if field == "" {
return false
}
if field == `\.` {
return true
}
if w.Comma < utf8.RuneSelf {
for i := 0; i < len(field); i++ {
c := field[i]
if c == '\n' || c == '\r' || c == '"' || c == byte(w.Comma) {
return true
}
}
} else {
if strings.ContainsRune(field, w.Comma) || strings.ContainsAny(field, "\"\r\n") {
return true
}
}
r1, _ := utf8.DecodeRuneInString(field)
return unicode.IsSpace(r1)
}

View file

@ -111,36 +111,6 @@ func (omap *OrderedMap) GetWithCheck(key string) (interface{}, bool) {
}
}
func (omap *OrderedMap) GetKeys() []string {
keys := make([]string, omap.FieldCount)
i := 0
for pe := omap.Head; pe != nil; pe = pe.Next {
keys[i] = pe.Key
i++
}
return keys
}
// Returns an array of keys, not including the ones specified. The ones
// specified are to be passed in as a map from string to bool, as Go
// doesn't have hash-sets.
func (omap *OrderedMap) GetKeysExcept(exceptions map[string]bool) []string {
keys := make([]string, 0)
for pe := omap.Head; pe != nil; pe = pe.Next {
if _, present := exceptions[pe.Key]; !present {
keys = append(keys, pe.Key)
}
}
return keys
}
// ----------------------------------------------------------------
func (omap *OrderedMap) Clear() {
omap.FieldCount = 0
omap.Head = nil
omap.Tail = nil
}
// ----------------------------------------------------------------
// Returns true if it was found and removed
func (omap *OrderedMap) Remove(key string) bool {

View file

@ -130,24 +130,6 @@ func GetVar(
// ----------------------------------------------------------------
// GetSkewness is the finalizing function for computing skewness from streamed
// accumulator values.
func GetSkewness(
nint int,
sumx float64,
sumx2 float64,
sumx3 float64,
) float64 {
n := float64(nint)
mean := sumx / n
numerator := sumx3 - mean*(3*sumx2-2*n*mean*mean)
numerator = numerator / n
denominator := (sumx2 - n*mean*mean) / (n - 1)
denominator = math.Pow(denominator, 1.5)
return numerator / denominator
}
// ----------------------------------------------------------------
// Unbiased:
// (1/n) sum{(x-mean)**4}
@ -163,23 +145,6 @@ func GetSkewness(
// = sumx4 - mean*(4 sumx3 - 6 mean sumx2 + 3 n mean^3)
// = sumx4 - mean*(4 sumx3 - mean*(6 sumx2 - 3 n mean^2))
func GetKurtosis(
nint int,
sumx float64,
sumx2 float64,
sumx3 float64,
sumx4 float64,
) float64 {
n := float64(nint)
mean := sumx / n
numerator := sumx4 - mean*(4*sumx3-mean*(6*sumx2-3*n*mean*mean))
numerator = numerator / n
denominator := (sumx2 - n*mean*mean) / n
denominator = denominator * denominator
return numerator/denominator - 3.0
}
// ----------------------------------------------------------------
// Non-streaming implementation:
//

View file

@ -929,7 +929,3 @@ func (mlrmap *Mlrmap) GetFirstPair() *Mlrmap {
pair.PutCopy(mlrmap.Head.Key, mlrmap.Head.Value)
return pair
}
func (mlrmap *Mlrmap) IsSinglePair() bool {
return mlrmap.FieldCount == 1
}

View file

@ -1,19 +1,6 @@
package mlrval
import (
"bytes"
"fmt"
"os"
)
// ----------------------------------------------------------------
func (mlrmap *Mlrmap) Print() {
mlrmap.Fprint(os.Stdout)
os.Stdout.WriteString("\n")
}
func (mlrmap *Mlrmap) Fprint(file *os.File) {
(*file).WriteString(mlrmap.ToDKVPString())
}
import "bytes"
func (mlrmap *Mlrmap) ToDKVPString() string {
var buffer bytes.Buffer // stdio is non-buffered in Go, so buffer for ~5x speed increase
@ -50,20 +37,3 @@ func (mlrmap Mlrmap) String() string {
return string(bytes) + "\n"
}
}
// ----------------------------------------------------------------
func (mlrmap *Mlrmap) Dump() {
fmt.Printf("FIELD COUNT: %d\n", mlrmap.FieldCount)
fmt.Printf("HEAD: %p\n", mlrmap.Head)
fmt.Printf("TAIL: %p\n", mlrmap.Tail)
fmt.Printf("KEYS TO ENTRIES:\n")
for k, e := range mlrmap.keysToEntries {
fmt.Printf(" %-10s %#v\n", k, e)
}
fmt.Printf("LIST:\n")
for pe := mlrmap.Head; pe != nil; pe = pe.Next {
fmt.Printf(" key: \"%s\" value: %-20s prev:%p self:%p next:%p\n",
pe.Key, pe.Value.String(), pe.Prev, pe, pe.Next,
)
}
}

View file

@ -88,12 +88,3 @@ func (mv *Mlrval) FlattenToMap(prefix string, delimiter string) Mlrval {
return *FromMap(retval)
}
// Increment is used by stats1.
func (mv *Mlrval) Increment() {
if mv.mvtype == MT_INT {
mv.intf = mv.intf.(int64) + 1
} else if mv.mvtype == MT_FLOAT {
mv.intf = mv.intf.(float64) + 1.0
}
}

View file

@ -70,8 +70,6 @@ package mlrval
import (
"errors"
"fmt"
"os"
"strconv"
"github.com/johnkerl/miller/v6/pkg/lib"
@ -95,41 +93,6 @@ func (mv *Mlrval) ArrayGet(mindex *Mlrval) Mlrval {
}
}
// ----------------------------------------------------------------
// TODO: make this return error so caller can do 'if err == nil { ... }'
func (mv *Mlrval) ArrayPut(mindex *Mlrval, value *Mlrval) {
if !mv.IsArray() {
fmt.Fprintf(
os.Stderr,
"mlr: expected array as indexed item in ArrayPut; got %s\n",
mv.GetTypeName(),
)
os.Exit(1)
}
if !mindex.IsInt() {
// TODO: need to be careful about semantics here.
// Silent no-ops are not good UX ...
fmt.Fprintf(
os.Stderr,
"mlr: expected int as index item ArrayPut; got %s\n",
mindex.GetTypeName(),
)
os.Exit(1)
}
arrayval := mv.intf.([]*Mlrval)
ok := arrayPutAliased(&arrayval, int(mindex.intf.(int64)), value)
if !ok {
fmt.Fprintf(
os.Stderr,
"mlr: array index %d out of bounds %d..%d\n",
mindex.intf.(int64), 1, len(arrayval),
)
os.Exit(1)
}
mv.intf = arrayval
}
// ----------------------------------------------------------------
func arrayGetAliased(array *[]*Mlrval, mindex int) *Mlrval {
zindex, ok := UnaliasArrayIndex(array, mindex)
@ -140,16 +103,6 @@ func arrayGetAliased(array *[]*Mlrval, mindex int) *Mlrval {
}
}
func arrayPutAliased(array *[]*Mlrval, mindex int, value *Mlrval) bool {
zindex, ok := UnaliasArrayIndex(array, mindex)
if ok {
(*array)[zindex] = value.Copy()
return true
} else {
return false
}
}
func UnaliasArrayIndex(array *[]*Mlrval, mindex int) (int, bool) {
n := int(len(*array))
return UnaliasArrayLengthIndex(n, mindex)

View file

@ -4,18 +4,6 @@
package mlrval
// MlrvalFromPending is designed solely for the JSON API, for something
// intended to be mutated after construction once its type is (later) known.
// Whereas ERROR, ABSENT, etc are all singletons, this one
// must be mutable and therefore non-singleton.
func MlrvalFromPending() Mlrval {
return Mlrval{
mvtype: MT_PENDING,
printrep: "(bug-if-you-see-this:case-3)", // INVALID_PRINTREP,
}
}
// These are made singletons as part of a copy-reduction effort. They're not
// marked const (I haven't figured out the right way to get that to compile;
// just using `const` isn't enough) but the gentelpersons' agreement is that

View file

@ -125,10 +125,6 @@ func FromNotCollectionError(funcname string, v *Mlrval) *Mlrval {
return FromNotNamedTypeError(funcname, v, "array or map")
}
func FromNotFunctionError(funcname string, v *Mlrval) *Mlrval {
return FromNotNamedTypeError(funcname, v, "function")
}
func FromNotNamedTypeError(funcname string, v *Mlrval, expected_type_name string) *Mlrval {
return FromError(
fmt.Errorf(
@ -182,13 +178,6 @@ func (mv *Mlrval) SetFromString(input string) *Mlrval {
return mv
}
func (mv *Mlrval) SetFromVoid() *Mlrval {
mv.printrep = ""
mv.printrepValid = true
mv.mvtype = MT_VOID
return mv
}
func FromInt(input int64) *Mlrval {
return &Mlrval{
mvtype: MT_INT,
@ -307,15 +296,6 @@ func FromBoolString(input string) *Mlrval {
}
}
// TODO: comment
func (mv *Mlrval) SetFromPrevalidatedBoolString(input string, boolval bool) *Mlrval {
mv.printrep = input
mv.printrepValid = true
mv.intf = boolval
mv.mvtype = MT_BOOL
return mv
}
// The user-defined function is of type 'interface{}' here to avoid what would
// otherwise be a package-dependency cycle between this package and
// github.com/johnkerl/miller/v6/pkg/dsl/cst.

View file

@ -82,21 +82,6 @@ func ParseLocation(value, format string, location *time.Location) (time.Time, er
return strptime_tz(value, format, _ignoreUnsupported, true, location)
}
// ParseStrict returns ErrFormatUnsupported for unsupported formats strings, but is otherwise
// identical to Parse.
func ParseStrict(value, format string) (time.Time, error) {
return strptime_tz(value, format, _ignoreUnsupported, false, nil)
}
// MustParse is a wrapper for Parse which panics on any error.
func MustParse(value, format string) time.Time {
t, err := strptime_tz(value, format, true, false, nil)
if err != nil {
panic(err)
}
return t
}
// Check verifies that format is a fully-supported strptime format string for this implementation.
// Not used by Miller.
func Check(format string) error {

View file

@ -178,13 +178,6 @@ func (stack *Stack) UnsetIndexed(
stack.head.unsetIndexed(stackVariable, indices)
}
func (stack *Stack) Dump() {
fmt.Printf("STACK FRAMESETS (count %d):\n", len(stack.stackFrameSets))
for _, stackFrameSet := range stack.stackFrameSets {
stackFrameSet.dump()
}
}
// ================================================================
// STACKFRAMESET METHODS
@ -210,16 +203,6 @@ func (frameset *StackFrameSet) popStackFrame() {
frameset.stackFrames = frameset.stackFrames[0 : len(frameset.stackFrames)-1]
}
func (frameset *StackFrameSet) dump() {
fmt.Printf(" STACK FRAMES (count %d):\n", len(frameset.stackFrames))
for _, stackFrame := range frameset.stackFrames {
fmt.Printf(" VARIABLES (count %d):\n", len(stackFrame.vars))
for _, v := range stackFrame.vars {
fmt.Printf(" %-16s %s\n", v.GetName(), v.ValueString())
}
}
}
// Returns nil on no-such
func (frameset *StackFrameSet) get(
stackVariable *StackVariable,

View file

@ -51,9 +51,9 @@ func NewEmptyState(options *cli.TOptions, strictMode bool) *State {
oosvars := mlrval.NewMlrmap()
return &State{
Inrec: nil,
Context: nil,
Oosvars: oosvars,
Inrec: nil,
Context: nil,
Oosvars: oosvars,
// XXX
//FilterExpression: mlrval.TRUE,
FilterExpression: mlrval.NULL,

View file

@ -154,18 +154,3 @@ func (keeper *PercentileKeeper) EmitNamed(name string) *mlrval.Mlrval {
)
}
}
// ----------------------------------------------------------------
func (keeper *PercentileKeeper) Dump() {
fmt.Printf("percentile_keeper dump:\n")
for i, datum := range keeper.data {
ival, ok := datum.GetIntValue()
if ok {
fmt.Printf("[%02d] %d\n", i, ival)
}
fval, ok := datum.GetFloatValue()
if ok {
fmt.Printf("[%02d] %.8f\n", i, fval)
}
}
}

View file

@ -145,11 +145,6 @@ func (context *Context) UpdateForInputRecord() {
context.FNR++
}
func (context *Context) Copy() *Context {
other := *context
return &other
}
func (context *Context) GetStatusString() string {
var buffer bytes.Buffer // stdio is non-buffered in Go, so buffer for speed increase

View file

@ -72,18 +72,10 @@ func NewTypeGatedMlrvalVariable(
}, nil
}
func (tvar *TypeGatedMlrvalVariable) GetName() string {
return tvar.typeGatedMlrvalName.Name
}
func (tvar *TypeGatedMlrvalVariable) GetValue() *mlrval.Mlrval {
return tvar.value
}
func (tvar *TypeGatedMlrvalVariable) ValueString() string {
return tvar.value.String()
}
func (tvar *TypeGatedMlrvalVariable) Assign(value *mlrval.Mlrval) error {
err := tvar.typeGatedMlrvalName.Check(value)
if err != nil {

View file

@ -1,10 +1,12 @@
#!/bin/bash
echo "LINES:"
wc -l \
$(find pkg -name '*.go' | grep -v pkg/parsing) pkg/parsing/mlr.bnf \
| sort -n
echo
echo "CHARACTERS:"
wc -c \
$(find pkg -name '*.go' | grep -v pkg/parsing) pkg/parsing/mlr.bnf \
| sort -n \