diff --git a/pkg/bifs/arithmetic.go b/pkg/bifs/arithmetic.go index fc8309775..0ad936df6 100644 --- a/pkg/bifs/arithmetic.go +++ b/pkg/bifs/arithmetic.go @@ -545,70 +545,6 @@ func BIF_dot_divide(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { return dotdivide_dispositions[input1.Type()][input2.Type()](input1, input2) } -// 64-bit integer division: DSL operator './/'. See also -// https://miller.readthedocs.io/en/latest/reference-main-arithmetic - -func dotidivide_i_ii(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { - a := input1.AcquireIntValue() - b := input2.AcquireIntValue() - - if b == 0 { - // Compute inf/nan as with floats rather than fatal runtime FPE on integer divide by zero - return mlrval.FromFloat(float64(a) / float64(b)) - } - - // Pythonic division, not C division. - q := a / b - r := a % b - if a < 0 { - if b > 0 { - if r != 0 { - q-- - } - } - } else { - if b < 0 { - if r != 0 { - q-- - } - } - } - return mlrval.FromInt(q) -} - -func dotidivide_f_if(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { - return mlrval.FromFloat(math.Floor(float64(input1.AcquireIntValue()) / input2.AcquireFloatValue())) -} -func dotidivide_f_fi(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { - return mlrval.FromFloat(math.Floor(input1.AcquireFloatValue() / float64(input2.AcquireIntValue()))) -} -func dotidivide_f_ff(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { - return mlrval.FromFloat(math.Floor(input1.AcquireFloatValue() / input2.AcquireFloatValue())) -} - -func didte(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { - return mlrval.FromTypeErrorBinary(".//", input1, input2) -} - -var dotidivide_dispositions = [mlrval.MT_DIM][mlrval.MT_DIM]BinaryFunc{ - // . INT FLOAT BOOL VOID STRING ARRAY MAP FUNC ERROR NULL ABSENT - /*INT */ {dotidivide_i_ii, dotidivide_f_if, didte, _void, didte, _absn, _absn, didte, didte, didte, _1___}, - /*FLOAT */ {dotidivide_f_fi, dotidivide_f_ff, didte, _void, didte, _absn, _absn, didte, didte, didte, _1___}, - /*BOOL */ {didte, didte, didte, didte, didte, _absn, _absn, didte, didte, didte, didte}, - /*VOID */ {_void, _void, didte, _void, didte, _absn, _absn, didte, didte, didte, _absn}, - /*STRING */ {didte, didte, didte, didte, didte, _absn, _absn, didte, didte, didte, didte}, - /*ARRAY */ {_absn, _absn, _absn, _absn, _absn, _absn, _absn, didte, _absn, _absn, _absn}, - /*MAP */ {_absn, _absn, _absn, _absn, _absn, _absn, _absn, didte, _absn, _absn, _absn}, - /*FUNC */ {didte, didte, didte, didte, didte, didte, didte, didte, didte, didte, didte}, - /*ERROR */ {didte, didte, didte, didte, didte, _absn, _absn, didte, didte, didte, didte}, - /*NULL */ {didte, didte, didte, didte, didte, _absn, _absn, didte, didte, didte, _absn}, - /*ABSENT */ {_2___, _2___, didte, _absn, didte, _absn, _absn, didte, didte, didte, _absn}, -} - -func BIF_dot_int_divide(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { - return dotidivide_dispositions[input1.Type()][input2.Type()](input1, input2) -} - // Modulus func modulus_i_ii(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval { diff --git a/pkg/bifs/arithmetic_test.go b/pkg/bifs/arithmetic_test.go index 393a3a968..8f83d22f0 100644 --- a/pkg/bifs/arithmetic_test.go +++ b/pkg/bifs/arithmetic_test.go @@ -78,7 +78,6 @@ func TestBIF_plus_binary_overflow(t *testing.T) { //func BIF_dot_minus(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval //func BIF_dot_times(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval //func BIF_dot_divide(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval -//func BIF_dot_int_divide(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval //func BIF_modulus(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval //func BIF_mod_add(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval //func BIF_mod_sub(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval diff --git a/pkg/bifs/base.go b/pkg/bifs/base.go index 29521261b..7d9671714 100644 --- a/pkg/bifs/base.go +++ b/pkg/bifs/base.go @@ -99,13 +99,6 @@ func _zero1(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.FromInt(0) } -// Return one (unary) -// -//lint:ignore U1000 util function might be used later -func __one1(input1 *mlrval.Mlrval) *mlrval.Mlrval { - return mlrval.FromInt(1) -} - // Return null (unary) func _null1(input1 *mlrval.Mlrval) *mlrval.Mlrval { return mlrval.NULL diff --git a/pkg/colorizer/colorizer.go b/pkg/colorizer/colorizer.go index facaf53da..e1676b736 100644 --- a/pkg/colorizer/colorizer.go +++ b/pkg/colorizer/colorizer.go @@ -58,20 +58,6 @@ func SetFailColor(name string) bool { } return ok } -func SetREPLPS1Color(name string) bool { - escape, ok := lumin.MakeANSIEscapesFromName(name) - if ok { - replPS1ColorString = escape - } - return ok -} -func SetREPLPS2Color(name string) bool { - escape, ok := lumin.MakeANSIEscapesFromName(name) - if ok { - replPS2ColorString = escape - } - return ok -} func SetHelpColor(name string) bool { escape, ok := lumin.MakeANSIEscapesFromName(name) if ok { diff --git a/pkg/dkvpx/dkvpx_writer.go b/pkg/dkvpx/dkvpx_writer.go index 98a73e0d1..f72a1a3f3 100644 --- a/pkg/dkvpx/dkvpx_writer.go +++ b/pkg/dkvpx/dkvpx_writer.go @@ -1,99 +1,12 @@ -// Package dkvpx (see also dkvpx_reader.go) writes DKVPX records: comma-delimited +// Package dkvpx (see also dkvpx_reader.go) handles DKVPX records: comma-delimited // key=value pairs with selective quoting. Keys and values are double-quoted only // when they contain comma, equals, newline, or double-quote. package dkvpx import ( - "bufio" - "io" "strings" - - "github.com/johnkerl/miller/v6/pkg/lib" ) -// A Writer writes DKVPX records. It mirrors the structure of csv.Writer. -type Writer struct { - Comma rune // Pair delimiter (set to ',' by NewWriter) - UseCRLF bool // True to use \r\n as the line terminator - w *bufio.Writer -} - -// NewWriter returns a new Writer that writes to w. -func NewWriter(w io.Writer) *Writer { - return &Writer{ - Comma: ',', - w: bufio.NewWriter(w), - } -} - -// Write writes a single DKVPX record. Keys and values are quoted only when -// they contain comma, equals, newline, or double-quote. -func (w *Writer) Write(record *lib.OrderedMap[string]) error { - if record == nil || record.IsEmpty() { - return w.writeLineEnd() - } - - first := true - for pe := record.Head; pe != nil; pe = pe.Next { - if !first { - if _, err := w.w.WriteRune(w.Comma); err != nil { - return err - } - } - first = false - - if err := w.writeQuotedIfNeeded(pe.Key); err != nil { - return err - } - if err := w.w.WriteByte('='); err != nil { - return err - } - if err := w.writeQuotedIfNeeded(pe.Value); err != nil { - return err - } - } - - return w.writeLineEnd() -} - -// writeQuotedIfNeeded writes the string, adding surrounding quotes and escaping -// internal quotes only when the string contains comma, equals, newline, or quote. -func (w *Writer) writeQuotedIfNeeded(s string) error { - if !needsQuoting(s) { - _, err := w.w.WriteString(s) - return err - } - - if err := w.w.WriteByte('"'); err != nil { - return err - } - // Escape " as "" - for len(s) > 0 { - i := strings.IndexAny(s, "\"\r\n") - if i < 0 { - i = len(s) - } - if _, err := w.w.WriteString(s[:i]); err != nil { - return err - } - s = s[i:] - if len(s) > 0 { - switch s[0] { - case '"': - if _, err := w.w.WriteString(`""`); err != nil { - return err - } - case '\r', '\n': - if err := w.w.WriteByte(s[0]); err != nil { - return err - } - } - s = s[1:] - } - } - return w.w.WriteByte('"') -} - // needsQuoting reports whether the string must be quoted (contains comma, // equals, newline, or double-quote). func needsQuoting(s string) bool { @@ -120,32 +33,3 @@ func FormatField(s string) string { b.WriteByte('"') return b.String() } - -func (w *Writer) writeLineEnd() error { - if w.UseCRLF { - _, err := w.w.WriteString("\r\n") - return err - } - return w.w.WriteByte('\n') -} - -// Flush writes any buffered data to the underlying io.Writer. -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 DKVPX records and then calls Flush. -func (w *Writer) WriteAll(records []*lib.OrderedMap[string]) error { - for _, record := range records { - if err := w.Write(record); err != nil { - return err - } - } - return w.w.Flush() -} diff --git a/pkg/dkvpx/dkvpx_writer_test.go b/pkg/dkvpx/dkvpx_writer_test.go index 66d5270b6..e64a6d227 100644 --- a/pkg/dkvpx/dkvpx_writer_test.go +++ b/pkg/dkvpx/dkvpx_writer_test.go @@ -4,68 +4,45 @@ import ( "strings" "testing" - "github.com/johnkerl/miller/v6/pkg/lib" "github.com/stretchr/testify/assert" ) -func TestWrite_Basic(t *testing.T) { - var buf strings.Builder - wr := NewWriter(&buf) - rec := lib.NewOrderedMap[string]() - rec.Put("x", "1") - rec.Put("y", "2") - rec.Put("z", "3") - err := wr.Write(rec) - assert.NoError(t, err) - wr.Flush() - assert.NoError(t, wr.Error()) - assert.Equal(t, "x=1,y=2,z=3\n", buf.String()) +func TestFormatField_Basic(t *testing.T) { + assert.Equal(t, "x", FormatField("x")) + assert.Equal(t, "1", FormatField("1")) + assert.Equal(t, "abc def", FormatField("abc def")) } -func TestWrite_QuotesWhenNeeded(t *testing.T) { - var buf strings.Builder - wr := NewWriter(&buf) - rec := lib.NewOrderedMap[string]() - rec.Put("x,y", "a,b,c") - rec.Put("z", "3") - err := wr.Write(rec) - assert.NoError(t, err) - wr.Flush() - assert.Equal(t, `"x,y"="a,b,c",z=3`+"\n", buf.String()) +func TestFormatField_QuotesWhenNeeded(t *testing.T) { + assert.Equal(t, `"x,y"`, FormatField("x,y")) + assert.Equal(t, `"a,b,c"`, FormatField("a,b,c")) } -func TestWrite_ValueWithEquals(t *testing.T) { - var buf strings.Builder - wr := NewWriter(&buf) - rec := lib.NewOrderedMap[string]() - rec.Put("a", "b=c") - err := wr.Write(rec) - assert.NoError(t, err) - wr.Flush() - assert.Equal(t, `a="b=c"`+"\n", buf.String()) +func TestFormatField_ValueWithEquals(t *testing.T) { + assert.Equal(t, `"b=c"`, FormatField("b=c")) } -func TestWrite_EscapedQuotes(t *testing.T) { - var buf strings.Builder - wr := NewWriter(&buf) - rec := lib.NewOrderedMap[string]() - rec.Put("x", `the "word"`) - err := wr.Write(rec) - assert.NoError(t, err) - wr.Flush() - assert.Equal(t, `x="the ""word"""`+"\n", buf.String()) +func TestFormatField_EscapedQuotes(t *testing.T) { + assert.Equal(t, `"the ""word"""`, FormatField(`the "word"`)) } -func TestWrite_RoundTrip(t *testing.T) { +func TestFormatField_RoundTrip(t *testing.T) { input := `"x,y"="a,b,c",z=3` + "\n" rdr := NewReader(strings.NewReader(input)) rec, err := rdr.Read() assert.NoError(t, err) - var buf strings.Builder - wr := NewWriter(&buf) - err = wr.Write(rec) - assert.NoError(t, err) - wr.Flush() - assert.Equal(t, input, buf.String()) + var sb strings.Builder + first := true + for pe := rec.Head; pe != nil; pe = pe.Next { + if !first { + sb.WriteByte(',') + } + first = false + sb.WriteString(FormatField(pe.Key)) + sb.WriteByte('=') + sb.WriteString(FormatField(pe.Value)) + } + sb.WriteByte('\n') + assert.Equal(t, input, sb.String()) } diff --git a/pkg/lib/logger.go b/pkg/lib/logger.go index 99a26d431..3c1a70a34 100644 --- a/pkg/lib/logger.go +++ b/pkg/lib/logger.go @@ -98,15 +98,3 @@ func InternalCodingErrorPanic(message string) { ) } } - -// WhereAreWe shows a stack trace from the current callsite. -func WhereAreWe() { - // Start at 1, not 0, since this function itself is not of interest. - for i := 1; i < 20; i++ { - _, fileName, fileLine, ok := runtime.Caller(i) - if !ok { - break - } - fmt.Printf(" %s %d\n", fileName, fileLine) - } -} diff --git a/pkg/lib/util.go b/pkg/lib/util.go index 24e4261a5..5811cc364 100644 --- a/pkg/lib/util.go +++ b/pkg/lib/util.go @@ -52,15 +52,6 @@ func StringListToSet(stringList []string) map[string]bool { return stringSet } -// ReverseStringList reverses strs in place. -// -// Deprecated: use slices.Reverse instead. -// -//go:fix inline -func ReverseStringList(strs []string) { - slices.Reverse(strs) -} - // SortedStrings returns a new slice containing the strings in strs in ascending order. func SortedStrings(strs []string) []string { result := make([]string, len(strs)) @@ -190,15 +181,6 @@ func WriteTempFileOrDie(contents string) string { return handle.Name() } -// CopyStringArray returns a copy of input. -// -// Deprecated: use slices.Clone instead. -// -//go:fix inline -func CopyStringArray(input []string) []string { - return slices.Clone(input) -} - func StripEmpties(input []string) []string { output := make([]string, 0, len(input)) for _, e := range input { diff --git a/pkg/mlrval/mlrval_cmp.go b/pkg/mlrval/mlrval_cmp.go index 9a85eba82..00110b066 100644 --- a/pkg/mlrval/mlrval_cmp.go +++ b/pkg/mlrval/mlrval_cmp.go @@ -27,9 +27,6 @@ type CmpFuncInt func(input1, input2 *Mlrval) int // -1, 0, 1 for <=> func Equals(input1, input2 *Mlrval) bool { return cmp_dispositions[input1.Type()][input2.Type()](input1, input2) == 0 } -func NotEquals(input1, input2 *Mlrval) bool { - return cmp_dispositions[input1.Type()][input2.Type()](input1, input2) != 0 -} func GreaterThan(input1, input2 *Mlrval) bool { return cmp_dispositions[input1.Type()][input2.Type()](input1, input2) > 0 } diff --git a/pkg/mlrval/mlrval_cmp_test.go b/pkg/mlrval/mlrval_cmp_test.go index 047f5bfa4..da52d6c4f 100644 --- a/pkg/mlrval/mlrval_cmp_test.go +++ b/pkg/mlrval/mlrval_cmp_test.go @@ -51,20 +51,6 @@ func TestEqual(t *testing.T) { } } -func TestNotEquals(t *testing.T) { - for i := range orderedMlrvals { - mvi := orderedMlrvals[i] - for j := range orderedMlrvals { - mvj := orderedMlrvals[j] - assert.Equal(t, i != j, NotEquals(mvi, mvj), fmt.Sprintf( - "slots i=%d type=%s value=%s, j=%d type=%s value=%s", - i, mvi.GetTypeName(), mvi.String(), - j, mvj.GetTypeName(), mvj.String(), - )) - } - } -} - func TestLessThan(t *testing.T) { for i := range orderedMlrvals { mvi := orderedMlrvals[i] diff --git a/pkg/mlrval/mlrval_infer.go b/pkg/mlrval/mlrval_infer.go index 988c85615..1b6dd0ebf 100644 --- a/pkg/mlrval/mlrval_infer.go +++ b/pkg/mlrval/mlrval_infer.go @@ -24,11 +24,6 @@ type tInferrer func(mv *Mlrval) *Mlrval var packageLevelInferrer tInferrer = inferNormally -// SetInferNormally is the default behavior. -func SetInferNormally() { - packageLevelInferrer = inferNormally -} - // SetInferrerOctalAsInt is for mlr -O. func SetInferrerOctalAsInt() { packageLevelInferrer = inferWithOctalAsInt diff --git a/pkg/scan/find.go b/pkg/scan/find.go index f3b0cadc9..f202e6c6e 100644 --- a/pkg/scan/find.go +++ b/pkg/scan/find.go @@ -1,7 +1,5 @@ package scan -import () - // TODO: comment re context // o grammar for numbers & case-through @@ -53,11 +51,6 @@ func FindScanType(sinput string) ScanType { return scanTypeString } -// Convenience function for unit test -func findScanTypeName(sinput string) string { - return TypeNames[FindScanType(sinput)] -} - func findScanTypePositiveNumberOrString(input []byte) ScanType { if len(input) == 0 { return scanTypeString diff --git a/pkg/scan/find_test.go b/pkg/scan/find_test.go index e1eba0437..c8f2aeb2c 100644 --- a/pkg/scan/find_test.go +++ b/pkg/scan/find_test.go @@ -6,6 +6,11 @@ import ( "github.com/stretchr/testify/assert" ) +// Convenience function for unit test +func findScanTypeName(sinput string) string { + return TypeNames[FindScanType(sinput)] +} + func TestFindScanTypeNameStrings(t *testing.T) { assert.Equal(t, typeNameString, findScanTypeName("")) assert.Equal(t, typeNameString, findScanTypeName("-")) diff --git a/pkg/terminals/script/types.go b/pkg/terminals/script/types.go index 89a255f98..78b358b78 100644 --- a/pkg/terminals/script/types.go +++ b/pkg/terminals/script/types.go @@ -15,8 +15,7 @@ import ( ) type Script struct { - exeName string - name string + name string doWarnings bool cstRootNode *cst.RootNode diff --git a/pkg/types/slice_list.go b/pkg/types/slice_list.go deleted file mode 100644 index ebd75d70b..000000000 --- a/pkg/types/slice_list.go +++ /dev/null @@ -1,34 +0,0 @@ -package types - -// List is a thin wrapper around a slice which functions as a list/queue. The Items attribute is -// exposed as public since I want iteration (at many, many callsites) to be easy. -type List[T any] struct { - Items []T -} - -func NewList[T any](capacity int) *List[T] { - return &List[T]{ - make([]T, 0, capacity), - } -} - -// Front will panic if the list is empty -func (ell *List[T]) Front() T { - return ell.Items[0] -} - -func (ell *List[T]) Len() int { - return len(ell.Items) -} - -func (ell *List[T]) PushBack(e T) { - ell.Items = append(ell.Items, e) -} - -func (ell *List[T]) PushBackMultiple(mell []T) { - ell.Items = append(ell.Items, mell...) -} - -func (ell *List[T]) Clear() { - ell.Items = ell.Items[0:0:cap(ell.Items)] -}