From b6846fcd0fcf9d777dbd7432e64be484484f94d5 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Sat, 26 Nov 2022 20:55:21 -0500 Subject: [PATCH] Convert mlrval polymorphism from struct to unionish interface (#1133) * Convert mlrval polymorphism from struct to unionish interface: arrayval/mapval/funcval * Convert mlrval polymorphism from struct to unionish interface:: boolval * Convert mlrval polymorphism from struct to unionish interface:: floatval * Convert mlrval polymorphism from struct to unionish interface:: intval --- cmd/sizes/main.go | 4 +- internal/pkg/mlrval/mlrmap_accessors.go | 12 +-- .../pkg/mlrval/mlrmap_flatten_unflatten.go | 16 ++-- internal/pkg/mlrval/mlrval_accessors.go | 18 ++--- internal/pkg/mlrval/mlrval_cmp.go | 10 +-- internal/pkg/mlrval/mlrval_collections.go | 79 +++++++++++-------- internal/pkg/mlrval/mlrval_constants.go | 9 ++- internal/pkg/mlrval/mlrval_copy.go | 12 +-- internal/pkg/mlrval/mlrval_get.go | 26 +++--- internal/pkg/mlrval/mlrval_infer.go | 2 +- internal/pkg/mlrval/mlrval_is.go | 6 +- internal/pkg/mlrval/mlrval_json.go | 12 +-- internal/pkg/mlrval/mlrval_new.go | 22 ++---- internal/pkg/mlrval/mlrval_new_test.go | 10 +-- internal/pkg/mlrval/mlrval_output.go | 28 ++----- internal/pkg/mlrval/mlrval_type.go | 26 ++---- scripts/chain-cmps.sh | 6 +- scripts/chain-lengths.sh | 6 +- scripts/time-big-files | 5 +- 19 files changed, 150 insertions(+), 159 deletions(-) diff --git a/cmd/sizes/main.go b/cmd/sizes/main.go index 33abe92b4..82a4905b0 100644 --- a/cmd/sizes/main.go +++ b/cmd/sizes/main.go @@ -2,7 +2,9 @@ // Experiments for type-inference performance optimization // ================================================================ -// go build github.com/johnkerl/miller/cmd/sizes +/* +go build github.com/johnkerl/miller/cmd/sizes +*/ package main diff --git a/internal/pkg/mlrval/mlrmap_accessors.go b/internal/pkg/mlrval/mlrmap_accessors.go index 7e5fa9978..e0553f99a 100644 --- a/internal/pkg/mlrval/mlrmap_accessors.go +++ b/internal/pkg/mlrval/mlrmap_accessors.go @@ -339,7 +339,7 @@ func (mlrmap *Mlrmap) getWithMlrvalArrayIndex(index *Mlrval) (*Mlrval, error) { current := mlrmap var retval *Mlrval = nil lib.InternalCodingErrorIf(!index.IsArray()) - array := index.x.arrayval + array := index.intf.([]*Mlrval) n := len(array) for i, piece := range array { next, err := current.GetWithMlrvalIndex(piece) @@ -350,7 +350,7 @@ func (mlrmap *Mlrmap) getWithMlrvalArrayIndex(index *Mlrval) (*Mlrval, error) { if !next.IsMap() { return nil, fmt.Errorf("mlr: cannot multi-index non-map.") } - current = next.x.mapval + current = next.intf.(*Mlrmap) } else { retval = next.Copy() } @@ -782,11 +782,11 @@ func (mlrmap *Mlrmap) SortByKeyRecursively() { for _, key := range keys { // Old record will be GC'ed: just move pointers - value := mlrmap.Get(key) - if value.IsMap() { - value.x.mapval.SortByKeyRecursively() + val := mlrmap.Get(key) + if val.IsMap() { + val.intf.(*Mlrmap).SortByKeyRecursively() } - other.PutReference(key, value) + other.PutReference(key, val) } *mlrmap = *other diff --git a/internal/pkg/mlrval/mlrmap_flatten_unflatten.go b/internal/pkg/mlrval/mlrmap_flatten_unflatten.go index 140e67286..bb91901b7 100644 --- a/internal/pkg/mlrval/mlrmap_flatten_unflatten.go +++ b/internal/pkg/mlrval/mlrmap_flatten_unflatten.go @@ -137,13 +137,14 @@ func (mlrmap *Mlrmap) CopyUnflattened( // Is the field name something dot something? if strings.Contains(pe.Key, separator) { arrayOfIndices := SplitAXHelper(pe.Key, separator) - lib.InternalCodingErrorIf(len(arrayOfIndices.x.arrayval) < 1) + arrayval := arrayOfIndices.intf.([]*Mlrval) + lib.InternalCodingErrorIf(len(arrayval) < 1) // If the input field name was "x.a" then remember the "x". - baseIndex := arrayOfIndices.x.arrayval[0].String() + baseIndex := arrayval[0].String() affectedBaseIndices[baseIndex] = true // Use PutIndexed to assign $x["a"] = 7, or $x["b"] = 8, etc. other.PutIndexed( - CopyMlrvalArray(arrayOfIndices.x.arrayval), + CopyMlrvalArray(arrayval), unflattenTerminal(pe.Value).Copy(), ) } else { @@ -187,13 +188,14 @@ func (mlrmap *Mlrmap) CopyUnflattenFields( // Is the field name something dot something? if strings.Contains(pe.Key, separator) { arrayOfIndices := SplitAXHelper(pe.Key, separator) - lib.InternalCodingErrorIf(len(arrayOfIndices.x.arrayval) < 1) + arrayval := arrayOfIndices.intf.([]*Mlrval) + lib.InternalCodingErrorIf(len(arrayval) < 1) // If the input field name was "x.a" then remember the "x". - baseIndex := arrayOfIndices.x.arrayval[0].String() + baseIndex := arrayval[0].String() if fieldNameSet[baseIndex] { // Use PutIndexed to assign $x["a"] = 7, or $x["b"] = 8, etc. other.PutIndexed( - CopyMlrvalArray(arrayOfIndices.x.arrayval), + CopyMlrvalArray(arrayval), unflattenTerminal(pe.Value).Copy(), ) affectedBaseIndices[baseIndex] = true @@ -247,7 +249,7 @@ func SplitAXHelper(input string, separator string) *Mlrval { output := FromArray(make([]*Mlrval, len(fields))) for i, field := range fields { - output.x.arrayval[i] = FromString(field) + output.intf.([]*Mlrval)[i] = FromString(field) } return output diff --git a/internal/pkg/mlrval/mlrval_accessors.go b/internal/pkg/mlrval/mlrval_accessors.go index 18ffb77cc..a33a2f441 100644 --- a/internal/pkg/mlrval/mlrval_accessors.go +++ b/internal/pkg/mlrval/mlrval_accessors.go @@ -8,7 +8,7 @@ import ( func (mv *Mlrval) GetArrayLength() (int, bool) { if mv.IsArray() { - return len(mv.x.arrayval), true + return len(mv.intf.([]*Mlrval)), true } else { return -999, false } @@ -35,13 +35,13 @@ func (mv *Mlrval) FlattenToMap(prefix string, delimiter string) Mlrval { if mv.IsMap() { // Without this, the for-loop below is zero-pass and fields with "{}" // values would disappear entirely in a JSON-to-CSV conversion. - if mv.x.mapval.IsEmpty() { + if mv.intf.(*Mlrmap).IsEmpty() { if prefix != "" { retval.PutCopy(prefix, FromString("{}")) } } - for pe := mv.x.mapval.Head; pe != nil; pe = pe.Next { + for pe := mv.intf.(*Mlrmap).Head; pe != nil; pe = pe.Next { nextPrefix := pe.Key if prefix != "" { nextPrefix = prefix + delimiter + nextPrefix @@ -49,7 +49,7 @@ func (mv *Mlrval) FlattenToMap(prefix string, delimiter string) Mlrval { if pe.Value.IsMap() || pe.Value.IsArray() { nextResult := pe.Value.FlattenToMap(nextPrefix, delimiter) lib.InternalCodingErrorIf(nextResult.mvtype != MT_MAP) - for pf := nextResult.x.mapval.Head; pf != nil; pf = pf.Next { + for pf := nextResult.intf.(*Mlrmap).Head; pf != nil; pf = pf.Next { retval.PutCopy(pf.Key, pf.Value.Copy()) } } else { @@ -60,13 +60,13 @@ func (mv *Mlrval) FlattenToMap(prefix string, delimiter string) Mlrval { } else if mv.IsArray() { // Without this, the for-loop below is zero-pass and fields with "[]" // values would disappear entirely in a JSON-to-CSV conversion. - if len(mv.x.arrayval) == 0 { + if len(mv.intf.([]*Mlrval)) == 0 { if prefix != "" { retval.PutCopy(prefix, FromString("[]")) } } - for zindex, value := range mv.x.arrayval { + for zindex, value := range mv.intf.([]*Mlrval) { nextPrefix := strconv.Itoa(zindex + 1) // Miller user-space indices are 1-up if prefix != "" { nextPrefix = prefix + delimiter + nextPrefix @@ -74,7 +74,7 @@ func (mv *Mlrval) FlattenToMap(prefix string, delimiter string) Mlrval { if value.IsMap() || value.IsArray() { nextResult := value.FlattenToMap(nextPrefix, delimiter) lib.InternalCodingErrorIf(nextResult.mvtype != MT_MAP) - for pf := nextResult.x.mapval.Head; pf != nil; pf = pf.Next { + for pf := nextResult.intf.(*Mlrmap).Head; pf != nil; pf = pf.Next { retval.PutCopy(pf.Key, pf.Value.Copy()) } } else { @@ -92,8 +92,8 @@ func (mv *Mlrval) FlattenToMap(prefix string, delimiter string) Mlrval { // Increment is used by stats1. func (mv *Mlrval) Increment() { if mv.mvtype == MT_INT { - mv.intval++ + mv.intf = mv.intf.(int64) + 1 } else if mv.mvtype == MT_FLOAT { - mv.floatval++ + mv.intf = mv.intf.(float64) + 1.0 } } diff --git a/internal/pkg/mlrval/mlrval_cmp.go b/internal/pkg/mlrval/mlrval_cmp.go index 0aadb6baf..c9968d65a 100644 --- a/internal/pkg/mlrval/mlrval_cmp.go +++ b/internal/pkg/mlrval/mlrval_cmp.go @@ -107,19 +107,19 @@ func cmp_b_ss(input1, input2 *Mlrval) int { return string_cmp(input1.printrep, input2.printrep) } func cmp_b_ii(input1, input2 *Mlrval) int { - return int_cmp(input1.intval, input2.intval) + return int_cmp(input1.intf.(int64), input2.intf.(int64)) } func cmp_b_if(input1, input2 *Mlrval) int { - return float_cmp(float64(input1.intval), input2.floatval) + return float_cmp(float64(input1.intf.(int64)), input2.intf.(float64)) } func cmp_b_fi(input1, input2 *Mlrval) int { - return float_cmp(input1.floatval, float64(input2.intval)) + return float_cmp(input1.intf.(float64), float64(input2.intf.(int64))) } func cmp_b_ff(input1, input2 *Mlrval) int { - return float_cmp(input1.floatval, input2.floatval) + return float_cmp(input1.intf.(float64), input2.intf.(float64)) } func cmp_b_bb(input1, input2 *Mlrval) int { - return int_cmp(int64(lib.BoolToInt(input1.boolval)), int64(lib.BoolToInt(input2.boolval))) + return int_cmp(int64(lib.BoolToInt(input1.intf.(bool))), int64(lib.BoolToInt(input2.intf.(bool)))) } // TODO: cmp on array & map diff --git a/internal/pkg/mlrval/mlrval_collections.go b/internal/pkg/mlrval/mlrval_collections.go index f76d35ff3..6674a044a 100644 --- a/internal/pkg/mlrval/mlrval_collections.go +++ b/internal/pkg/mlrval/mlrval_collections.go @@ -86,7 +86,8 @@ func (mv *Mlrval) ArrayGet(mindex *Mlrval) Mlrval { if !mindex.IsInt() { return *ERROR } - value := arrayGetAliased(&mv.x.arrayval, int(mindex.intval)) + arrayval := mv.intf.([]*Mlrval) + value := arrayGetAliased(&arrayval, int(mindex.intf.(int64))) if value == nil { return *ABSENT } else { @@ -116,15 +117,17 @@ func (mv *Mlrval) ArrayPut(mindex *Mlrval, value *Mlrval) { os.Exit(1) } - ok := arrayPutAliased(&mv.x.arrayval, int(mindex.intval), value) + 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.intval, 1, len(mv.x.arrayval), + mindex.intf.(int64), 1, len(arrayval), ) os.Exit(1) } + mv.intf = arrayval } // ---------------------------------------------------------------- @@ -213,7 +216,8 @@ func (mv *Mlrval) ArrayAppend(value *Mlrval) { // Silent no-ops are not good UX ... return } - mv.x.arrayval = append(mv.x.arrayval, value) + mv.intf = append(mv.intf.([]*Mlrval), value) + } // ================================================================ @@ -222,7 +226,7 @@ func (mv *Mlrval) MapGet(key *Mlrval) Mlrval { return *ERROR } - mval, err := mv.x.mapval.GetWithMlrvalIndex(key) + mval, err := mv.intf.(*Mlrmap).GetWithMlrvalIndex(key) if err != nil { // xxx maybe error-return in the API return *ERROR } @@ -243,9 +247,9 @@ func (mv *Mlrval) MapPut(key *Mlrval, value *Mlrval) { } if key.IsString() { - mv.x.mapval.PutCopy(key.printrep, value) + mv.intf.(*Mlrmap).PutCopy(key.printrep, value) } else if key.IsInt() { - mv.x.mapval.PutCopy(key.String(), value) + mv.intf.(*Mlrmap).PutCopy(key.String(), value) } // TODO: need to be careful about semantics here. // Silent no-ops are not good UX ... @@ -291,19 +295,25 @@ func (mv *Mlrval) PutIndexed(indices []*Mlrval, rvalue *Mlrval) error { lib.InternalCodingErrorIf(len(indices) < 1) if mv.IsMap() { - return putIndexedOnMap(mv.x.mapval, indices, rvalue) + return putIndexedOnMap(mv.intf.(*Mlrmap), indices, rvalue) } else if mv.IsArray() { - return putIndexedOnArray(&mv.x.arrayval, indices, rvalue) + arrayval := mv.intf.([]*Mlrval) + retval := putIndexedOnArray(&arrayval, indices, rvalue) + mv.intf = arrayval + return retval } else { baseIndex := indices[0] if baseIndex.IsString() { *mv = *FromEmptyMap() - return putIndexedOnMap(mv.x.mapval, indices, rvalue) + return putIndexedOnMap(mv.intf.(*Mlrmap), indices, rvalue) } else if baseIndex.IsInt() { *mv = *FromEmptyArray() - return putIndexedOnArray(&mv.x.arrayval, indices, rvalue) + arrayval := mv.intf.([]*Mlrval) + retval := putIndexedOnArray(&arrayval, indices, rvalue) + mv.intf = arrayval + return retval } else { return errors.New( "mlr: only maps and arrays are indexable; got " + mv.GetTypeName(), @@ -326,7 +336,7 @@ func putIndexedOnMap(baseMap *Mlrmap, indices []*Mlrval, rvalue *Mlrval) error { ".", ) } - *baseMap = *rvalue.x.mapval.Copy() + *baseMap = *rvalue.intf.(*Mlrmap).Copy() return nil } @@ -379,21 +389,21 @@ func putIndexedOnArray( ".", ) } - zindex, inBounds := UnaliasArrayIndex(baseArray, int(mindex.intval)) + zindex, inBounds := UnaliasArrayIndex(baseArray, int(mindex.intf.(int64))) if numIndices == 1 { // If last index, then assign. if inBounds { (*baseArray)[zindex] = rvalue.Copy() - } else if mindex.intval == 0 { + } else if mindex.intf.(int64) == 0 { return errors.New("mlr: zero indices are not supported. Indices are 1-up.") - } else if mindex.intval < 0 { + } else if mindex.intf.(int64) < 0 { return errors.New("mlr: Cannot use negative indices to auto-lengthen arrays.") } else { // Array is [a,b,c] with mindices 1,2,3. Length is 3. Zindices are 0,1,2. // Given mindex is 4. - LengthenMlrvalArray(baseArray, int(mindex.intval)) - zindex := mindex.intval - 1 + LengthenMlrvalArray(baseArray, int(mindex.intf.(int64))) + zindex := mindex.intf.(int64) - 1 (*baseArray)[zindex] = rvalue.Copy() } return nil @@ -420,14 +430,14 @@ func putIndexedOnArray( return (*baseArray)[zindex].PutIndexed(indices[1:], rvalue) - } else if mindex.intval == 0 { + } else if mindex.intf.(int64) == 0 { return errors.New("mlr: zero indices are not supported. Indices are 1-up.") - } else if mindex.intval < 0 { + } else if mindex.intf.(int64) < 0 { return errors.New("mlr: Cannot use negative indices to auto-lengthen arrays.") } else { // Already allocated but needs to be longer - LengthenMlrvalArray(baseArray, int(mindex.intval)) - zindex := mindex.intval - 1 + LengthenMlrvalArray(baseArray, int(mindex.intf.(int64))) + zindex := mindex.intf.(int64) - 1 return (*baseArray)[zindex].PutIndexed(indices[1:], rvalue) } } @@ -438,10 +448,13 @@ func (mv *Mlrval) RemoveIndexed(indices []*Mlrval) error { lib.InternalCodingErrorIf(len(indices) < 1) if mv.IsMap() { - return removeIndexedOnMap(mv.x.mapval, indices) + return removeIndexedOnMap(mv.intf.(*Mlrmap), indices) } else if mv.IsArray() { - return removeIndexedOnArray(&mv.x.arrayval, indices) + arrayval := mv.intf.([]*Mlrval) + retval := removeIndexedOnArray(&arrayval, indices) + mv.intf = arrayval + return retval } else { return errors.New( @@ -505,7 +518,7 @@ func removeIndexedOnArray( ".", ) } - zindex, inBounds := UnaliasArrayIndex(baseArray, int(mindex.intval)) + zindex, inBounds := UnaliasArrayIndex(baseArray, int(mindex.intf.(int64))) // If last index, then unset. if numIndices == 1 { @@ -513,7 +526,7 @@ func removeIndexedOnArray( leftSlice := (*baseArray)[0:zindex] rightSlice := (*baseArray)[zindex+1 : len((*baseArray))] *baseArray = append(leftSlice, rightSlice...) - } else if mindex.intval == 0 { + } else if mindex.intf.(int64) == 0 { return errors.New("mlr: zero indices are not supported. Indices are 1-up.") } else { // TODO: improve wording @@ -523,7 +536,7 @@ func removeIndexedOnArray( // More indices remain; recurse if inBounds { return (*baseArray)[zindex].RemoveIndexed(indices[1:]) - } else if mindex.intval == 0 { + } else if mindex.intf.(int64) == 0 { return errors.New("mlr: zero indices are not supported. Indices are 1-up.") } else { // TODO: improve wording @@ -659,13 +672,13 @@ func NewMlrvalForAutoDeepen(mvtype MVType) (*Mlrval, error) { func (mv *Mlrval) Arrayify() *Mlrval { if mv.IsMap() { - if mv.x.mapval.IsEmpty() { + if mv.intf.(*Mlrmap).IsEmpty() { return mv } convertible := true i := 0 - for pe := mv.x.mapval.Head; pe != nil; pe = pe.Next { + for pe := mv.intf.(*Mlrmap).Head; pe != nil; pe = pe.Next { sval := strconv.Itoa(i + 1) // Miller user-space indices are 1-up i++ if pe.Key != sval { @@ -675,9 +688,9 @@ func (mv *Mlrval) Arrayify() *Mlrval { } if convertible { - arrayval := make([]*Mlrval, mv.x.mapval.FieldCount) + arrayval := make([]*Mlrval, mv.intf.(*Mlrmap).FieldCount) i := 0 - for pe := mv.x.mapval.Head; pe != nil; pe = pe.Next { + for pe := mv.intf.(*Mlrmap).Head; pe != nil; pe = pe.Next { arrayval[i] = pe.Value.Copy() i++ } @@ -690,9 +703,11 @@ func (mv *Mlrval) Arrayify() *Mlrval { } else if mv.IsArray() { // TODO: comment (or rethink) that this modifies its inputs!! output := mv.Copy() - for i := range mv.x.arrayval { - output.x.arrayval[i] = output.x.arrayval[i].Arrayify() + arrayval := mv.intf.([]*Mlrval) + for i := range arrayval { + arrayval[i] = arrayval[i].Arrayify() } + mv.intf = arrayval return output } else { diff --git a/internal/pkg/mlrval/mlrval_constants.go b/internal/pkg/mlrval/mlrval_constants.go index 5785616ed..3cc09d98e 100644 --- a/internal/pkg/mlrval/mlrval_constants.go +++ b/internal/pkg/mlrval/mlrval_constants.go @@ -25,13 +25,14 @@ var TRUE = &Mlrval{ mvtype: MT_BOOL, printrep: "true", printrepValid: true, - boolval: true, + intf: true, } var FALSE = &Mlrval{ mvtype: MT_BOOL, printrep: "false", printrepValid: true, + intf: false, } var VOID = &Mlrval{ @@ -63,19 +64,19 @@ var MINUS_ONE = &Mlrval{ mvtype: MT_INT, printrep: "-1", printrepValid: true, - intval: -1, + intf: int64(-1), } var ZERO = &Mlrval{ mvtype: MT_INT, printrep: "0", printrepValid: true, - intval: 0, + intf: int64(0), } var ONE = &Mlrval{ mvtype: MT_INT, printrep: "1", printrepValid: true, - intval: 1, + intf: int64(1), } diff --git a/internal/pkg/mlrval/mlrval_copy.go b/internal/pkg/mlrval/mlrval_copy.go index 7d1067e89..8b3530e72 100644 --- a/internal/pkg/mlrval/mlrval_copy.go +++ b/internal/pkg/mlrval/mlrval_copy.go @@ -4,17 +4,9 @@ package mlrval func (mv *Mlrval) Copy() *Mlrval { other := *mv if mv.mvtype == MT_MAP { - other.x = &mlrvalExtended{ - mapval: mv.x.mapval.Copy(), - } + other.intf = mv.intf.(*Mlrmap).Copy() } else if mv.mvtype == MT_ARRAY { - other.x = &mlrvalExtended{ - arrayval: CopyMlrvalArray(mv.x.arrayval), - } - } else if mv.mvtype == MT_FUNC { - other.x = &mlrvalExtended{ - funcval: mv.x.funcval, - } + other.intf = CopyMlrvalArray(mv.intf.([]*Mlrval)) } return &other } diff --git a/internal/pkg/mlrval/mlrval_get.go b/internal/pkg/mlrval/mlrval_get.go index 9cd2fd4db..68d15e866 100644 --- a/internal/pkg/mlrval/mlrval_get.go +++ b/internal/pkg/mlrval/mlrval_get.go @@ -25,7 +25,7 @@ func (mv *Mlrval) GetStringValue() (stringValue string, isString bool) { func (mv *Mlrval) GetIntValue() (intValue int64, isInt bool) { if mv.Type() == MT_INT { - return mv.intval, true + return mv.intf.(int64), true } else { return -999, false } @@ -33,7 +33,7 @@ func (mv *Mlrval) GetIntValue() (intValue int64, isInt bool) { func (mv *Mlrval) GetFloatValue() (floatValue float64, isFloat bool) { if mv.Type() == MT_FLOAT { - return mv.floatval, true + return mv.intf.(float64), true } else { return -777.0, false } @@ -41,9 +41,9 @@ func (mv *Mlrval) GetFloatValue() (floatValue float64, isFloat bool) { func (mv *Mlrval) GetNumericToFloatValue() (floatValue float64, isFloat bool) { if mv.Type() == MT_FLOAT { - return mv.floatval, true + return mv.intf.(float64), true } else if mv.Type() == MT_INT { - return float64(mv.intval), true + return float64(mv.intf.(int64)), true } else { return -888.0, false } @@ -57,7 +57,7 @@ func (mv *Mlrval) GetNumericNegativeorDie() bool { func (mv *Mlrval) GetBoolValue() (boolValue bool, isBool bool) { if mv.Type() == MT_BOOL { - return mv.boolval, true + return mv.intf.(bool), true } else { return false, false } @@ -65,7 +65,7 @@ func (mv *Mlrval) GetBoolValue() (boolValue bool, isBool bool) { func (mv *Mlrval) GetArray() []*Mlrval { if mv.IsArray() { - return mv.x.arrayval + return mv.intf.([]*Mlrval) } else { return nil } @@ -73,7 +73,7 @@ func (mv *Mlrval) GetArray() []*Mlrval { func (mv *Mlrval) GetMap() *Mlrmap { if mv.IsMap() { - return mv.x.mapval + return mv.intf.(*Mlrmap) } else { return nil } @@ -81,7 +81,7 @@ func (mv *Mlrval) GetMap() *Mlrmap { func (mv *Mlrval) GetFunction() interface{} { if mv.Type() == MT_FUNC { - return mv.x.funcval + return mv.intf } else { return nil } @@ -107,27 +107,27 @@ func (mv *Mlrval) AcquireStringValue() string { func (mv *Mlrval) AcquireIntValue() int64 { lib.InternalCodingErrorIf(mv.mvtype != MT_INT) - return mv.intval + return mv.intf.(int64) } func (mv *Mlrval) AcquireFloatValue() float64 { lib.InternalCodingErrorIf(mv.mvtype != MT_FLOAT) - return mv.floatval + return mv.intf.(float64) } func (mv *Mlrval) AcquireBoolValue() bool { lib.InternalCodingErrorIf(mv.mvtype != MT_BOOL) - return mv.boolval + return mv.intf.(bool) } func (mv *Mlrval) AcquireArrayValue() []*Mlrval { lib.InternalCodingErrorIf(mv.mvtype != MT_ARRAY) - return mv.x.arrayval + return mv.intf.([]*Mlrval) } func (mv *Mlrval) AcquireMapValue() *Mlrmap { lib.InternalCodingErrorIf(mv.mvtype != MT_MAP) - return mv.x.mapval + return mv.intf.(*Mlrmap) } func (mv *Mlrval) GetNumericToFloatValueOrDie() (floatValue float64) { diff --git a/internal/pkg/mlrval/mlrval_infer.go b/internal/pkg/mlrval/mlrval_infer.go index dfd4c8916..0e8df93e5 100644 --- a/internal/pkg/mlrval/mlrval_infer.go +++ b/internal/pkg/mlrval/mlrval_infer.go @@ -61,7 +61,7 @@ func inferWithOctalAsInt(mv *Mlrval) *Mlrval { func inferWithIntAsFloat(mv *Mlrval) *Mlrval { inferNormally(mv) if mv.Type() == MT_INT { - mv.floatval = float64(mv.intval) + mv.intf = float64(mv.intf.(int64)) mv.mvtype = MT_FLOAT } return mv diff --git a/internal/pkg/mlrval/mlrval_is.go b/internal/pkg/mlrval/mlrval_is.go index e5b449e12..900b0e985 100644 --- a/internal/pkg/mlrval/mlrval_is.go +++ b/internal/pkg/mlrval/mlrval_is.go @@ -96,7 +96,7 @@ func (mv *Mlrval) IsNumeric() bool { } func (mv *Mlrval) IsIntZero() bool { - return mv.Type() == MT_INT && mv.intval == 0 + return mv.Type() == MT_INT && mv.intf.(int64) == 0 } func (mv *Mlrval) IsBool() bool { @@ -104,10 +104,10 @@ func (mv *Mlrval) IsBool() bool { } func (mv *Mlrval) IsTrue() bool { - return mv.Type() == MT_BOOL && mv.boolval == true + return mv.Type() == MT_BOOL && mv.intf.(bool) == true } func (mv *Mlrval) IsFalse() bool { - return mv.Type() == MT_BOOL && mv.boolval == false + return mv.Type() == MT_BOOL && mv.intf.(bool) == false } func (mv *Mlrval) IsArray() bool { diff --git a/internal/pkg/mlrval/mlrval_json.go b/internal/pkg/mlrval/mlrval_json.go index 9395057f4..087f52338 100644 --- a/internal/pkg/mlrval/mlrval_json.go +++ b/internal/pkg/mlrval/mlrval_json.go @@ -411,7 +411,7 @@ func (mv *Mlrval) marshalJSONArray( // TODO: libify allTerminal := true - for _, element := range mv.x.arrayval { + for _, element := range mv.intf.([]*Mlrval) { if element.IsArrayOrMap() { allTerminal = false break @@ -429,11 +429,11 @@ func (mv *Mlrval) marshalJSONArraySingleLine( elementNestingDepth int, outputIsStdout bool, ) (string, error) { - n := len(mv.x.arrayval) + n := len(mv.intf.([]*Mlrval)) var buffer bytes.Buffer buffer.WriteByte('[') - for i, element := range mv.x.arrayval { + for i, element := range mv.intf.([]*Mlrval) { elementString, err := element.marshalJSONAux(JSON_SINGLE_LINE, elementNestingDepth+1, outputIsStdout) if err != nil { return "", err @@ -466,7 +466,7 @@ func (mv *Mlrval) marshalJSONArrayMultipleLines( elementNestingDepth int, outputIsStdout bool, ) (string, error) { - n := len(mv.x.arrayval) + n := len(mv.intf.([]*Mlrval)) var buffer bytes.Buffer // Write empty array as '[]' @@ -475,7 +475,7 @@ func (mv *Mlrval) marshalJSONArrayMultipleLines( buffer.WriteByte('\n') } - for i, element := range mv.x.arrayval { + for i, element := range mv.intf.([]*Mlrval) { elementString, err := element.marshalJSONAux(jsonFormatting, elementNestingDepth+1, outputIsStdout) if err != nil { return "", err @@ -508,7 +508,7 @@ func (mv *Mlrval) marshalJSONMap( outputIsStdout bool, ) (string, error) { lib.InternalCodingErrorIf(mv.mvtype != MT_MAP) - s, err := mv.x.mapval.marshalJSONAux(jsonFormatting, elementNestingDepth, outputIsStdout) + s, err := mv.intf.(*Mlrmap).marshalJSONAux(jsonFormatting, elementNestingDepth, outputIsStdout) if err != nil { return "", err } diff --git a/internal/pkg/mlrval/mlrval_new.go b/internal/pkg/mlrval/mlrval_new.go index d5a4a932a..0ac8d2613 100644 --- a/internal/pkg/mlrval/mlrval_new.go +++ b/internal/pkg/mlrval/mlrval_new.go @@ -83,7 +83,7 @@ func FromInt(input int64) *Mlrval { return &Mlrval{ mvtype: MT_INT, printrepValid: false, - intval: input, + intf: input, } } @@ -112,7 +112,7 @@ func TryFromIntString(input string) *Mlrval { func (mv *Mlrval) SetFromPrevalidatedIntString(input string, intval int64) *Mlrval { mv.printrep = input mv.printrepValid = true - mv.intval = intval + mv.intf = intval mv.mvtype = MT_INT return mv } @@ -128,7 +128,7 @@ func FromFloat(input float64) *Mlrval { return &Mlrval{ mvtype: MT_FLOAT, printrepValid: false, - floatval: input, + intf: input, } } @@ -157,7 +157,7 @@ func TryFromFloatString(input string) *Mlrval { func (mv *Mlrval) SetFromPrevalidatedFloatString(input string, floatval float64) *Mlrval { mv.printrep = input mv.printrepValid = true - mv.floatval = floatval + mv.intf = floatval mv.mvtype = MT_FLOAT return mv } @@ -192,7 +192,7 @@ func FromBoolString(input string) *Mlrval { func (mv *Mlrval) SetFromPrevalidatedBoolString(input string, boolval bool) *Mlrval { mv.printrep = input mv.printrepValid = true - mv.boolval = boolval + mv.intf = boolval mv.mvtype = MT_BOOL return mv } @@ -209,9 +209,7 @@ func FromFunction(funcval interface{}, name string) *Mlrval { mvtype: MT_FUNC, printrep: name, printrepValid: true, - x: &mlrvalExtended{ - funcval: funcval, - }, + intf: funcval, } } @@ -220,9 +218,7 @@ func FromArray(arrayval []*Mlrval) *Mlrval { mvtype: MT_ARRAY, printrep: "(bug-if-you-see-this:case-4)", // INVALID_PRINTREP, printrepValid: false, - x: &mlrvalExtended{ - arrayval: CopyMlrvalArray(arrayval), - }, + intf: CopyMlrvalArray(arrayval), } } @@ -235,9 +231,7 @@ func FromMap(mapval *Mlrmap) *Mlrval { mvtype: MT_MAP, printrep: "(bug-if-you-see-this:case-5)", // INVALID_PRINTREP, printrepValid: false, - x: &mlrvalExtended{ - mapval: mapval.Copy(), - }, + intf: mapval.Copy(), } } diff --git a/internal/pkg/mlrval/mlrval_new_test.go b/internal/pkg/mlrval/mlrval_new_test.go index b7f21a7db..fe10bf4fd 100644 --- a/internal/pkg/mlrval/mlrval_new_test.go +++ b/internal/pkg/mlrval/mlrval_new_test.go @@ -37,13 +37,13 @@ func TestFromInferredType(t *testing.T) { assert.Equal(t, MT_INT, mv.mvtype) assert.Equal(t, "123", mv.printrep) assert.True(t, mv.printrepValid) - assert.Equal(t, mv.intval, int64(123)) + assert.Equal(t, mv.intf.(int64), int64(123)) mv = FromInferredType("true") assert.Equal(t, MT_BOOL, mv.mvtype) assert.Equal(t, "true", mv.printrep) assert.True(t, mv.printrepValid) - assert.Equal(t, mv.boolval, true) + assert.Equal(t, mv.intf.(bool), true) mv = FromInferredType("abc") assert.Equal(t, MT_STRING, mv.mvtype) @@ -124,17 +124,17 @@ func TestFromFunction(t *testing.T) { mv := FromFunction("test data", "f001") assert.Equal(t, MT_FUNC, mv.mvtype) assert.True(t, mv.printrepValid) - assert.Equal(t, "test data", mv.x.funcval.(string)) + assert.Equal(t, "test data", mv.intf.(string)) } func TestFromArray(t *testing.T) { mv := FromArray([]*Mlrval{FromInt(10)}) assert.Equal(t, MT_ARRAY, mv.mvtype) - assert.Equal(t, 1, len(mv.x.arrayval)) + assert.Equal(t, 1, len(mv.intf.([]*Mlrval))) } func TestFromMap(t *testing.T) { mv := FromMap(NewMlrmap()) assert.Equal(t, MT_MAP, mv.mvtype) - assert.True(t, mv.x.mapval.IsEmpty()) + assert.True(t, mv.intf.(*Mlrmap).IsEmpty()) } diff --git a/internal/pkg/mlrval/mlrval_output.go b/internal/pkg/mlrval/mlrval_output.go index 078b61f44..7b354b359 100644 --- a/internal/pkg/mlrval/mlrval_output.go +++ b/internal/pkg/mlrval/mlrval_output.go @@ -19,7 +19,7 @@ func (mv *Mlrval) String() string { //if floatOutputFormatter != nil && (mv.mvtype == MT_FLOAT || mv.mvtype == MT_PENDING) { if floatOutputFormatter != nil && mv.Type() == MT_FLOAT { // Use the format string from global --ofmt, if supplied - return floatOutputFormatter.FormatFloat(mv.floatval) + return floatOutputFormatter.FormatFloat(mv.intf.(float64)) } // TODO: track dirty-flag checking / somesuch. @@ -71,13 +71,13 @@ func (mv *Mlrval) setPrintRep() { break case MT_INT: - mv.printrep = strconv.FormatInt(mv.intval, 10) + mv.printrep = strconv.FormatInt(mv.intf.(int64), 10) case MT_FLOAT: - mv.printrep = strconv.FormatFloat(mv.floatval, 'f', -1, 64) + mv.printrep = strconv.FormatFloat(mv.intf.(float64), 'f', -1, 64) case MT_BOOL: - if mv.boolval == true { + if mv.intf.(bool) == true { mv.printrep = "true" } else { mv.printrep = "false" @@ -110,12 +110,12 @@ func (mv *Mlrval) StringifyValuesRecursively() { switch mv.mvtype { case MT_ARRAY: - for i, _ := range mv.x.arrayval { - mv.x.arrayval[i].StringifyValuesRecursively() + for i, _ := range mv.intf.([]*Mlrval) { + mv.intf.([]*Mlrval)[i].StringifyValuesRecursively() } case MT_MAP: - for pe := mv.x.mapval.Head; pe != nil; pe = pe.Next { + for pe := mv.intf.(*Mlrmap).Head; pe != nil; pe = pe.Next { pe.Value.StringifyValuesRecursively() } @@ -126,20 +126,8 @@ func (mv *Mlrval) StringifyValuesRecursively() { func (mv *Mlrval) ShowSizes() { fmt.Printf("TOTAL %p %d\n", mv, reflect.TypeOf(*mv).Size()) - fmt.Printf("mv.intval %p %d\n", &mv.intval, reflect.TypeOf(mv.intval).Size()) - fmt.Printf("mv.floatval %p %d\n", &mv.floatval, reflect.TypeOf(mv.floatval).Size()) + //fmt.Printf("mv.intf %p %d\n", &mv.intf, reflect.TypeOf(mv.intf).Size()) fmt.Printf("mv.printrep %p %d\n", &mv.printrep, reflect.TypeOf(mv.printrep).Size()) - - fmt.Printf("mv.x %p %d\n", &mv.mvtype, reflect.TypeOf(mv.x).Size()) - if mv.x != nil { - fmt.Printf("mv.x.arrayval %p %d\n", &mv.x.arrayval, reflect.TypeOf(mv.x.arrayval).Size()) - fmt.Printf("mv.x.mapval %p %d\n", &mv.x.mapval, reflect.TypeOf(mv.x.mapval).Size()) - if mv.x.funcval != nil { - fmt.Printf("mv.x.funcval %p %d\n", &mv.x.funcval, reflect.TypeOf(mv.x.funcval).Size()) - } - } - fmt.Printf("mv.printrepValid %p %d\n", &mv.printrepValid, reflect.TypeOf(mv.printrepValid).Size()) - fmt.Printf("mv.boolval %p %d\n", &mv.boolval, reflect.TypeOf(mv.boolval).Size()) fmt.Printf("mv.mvtype %p %d\n", &mv.mvtype, reflect.TypeOf(mv.mvtype).Size()) } diff --git a/internal/pkg/mlrval/mlrval_type.go b/internal/pkg/mlrval/mlrval_type.go index 84a3f33ae..ace7805dd 100644 --- a/internal/pkg/mlrval/mlrval_type.go +++ b/internal/pkg/mlrval/mlrval_type.go @@ -54,30 +54,14 @@ package mlrval type Mlrval struct { - intval int64 - floatval float64 - printrep string - - x *mlrvalExtended - + printrep string + intf interface{} printrepValid bool - boolval bool - // Enumeration for string / int / float / boolean / etc. // I would call this "type" not "mvtype" but "type" is a keyword in Go. mvtype MVType } -// The Mlrval type is a (non-union) compound type where arrayval, mapval, and funcval are (a) -// largish, and (b) not usually used. -type mlrvalExtended struct { - arrayval []*Mlrval - mapval *Mlrmap - // First-class-function literals from internal/pkg/dsl/cst. - // Interfaced here to avoid package-dependency cycles. - funcval interface{} -} - const INVALID_PRINTREP = "(bug-if-you-see-this:case-2)" const ERROR_PRINTREP = "(error)" const ABSENT_PRINTREP = "(absent)" @@ -108,10 +92,13 @@ const ( // optimization. MT_PENDING MVType = -1 + // intf is int64 MT_INT MVType = 0 + // intf is float64 MT_FLOAT MVType = 1 + // intf is bool MT_BOOL MVType = 2 // Key present in input record with empty value, e.g. input data '$x=,$y=2' @@ -119,10 +106,13 @@ const ( MT_STRING MVType = 4 + // intf is []*Mlrval MT_ARRAY MVType = 5 + // intf is *Mlrmap MT_MAP MVType = 6 + // intf is interface{} -- resolved in the cst package to avoid circular dependencies MT_FUNC MVType = 7 // E.g. error encountered in one eval & it propagates up the AST at diff --git a/scripts/chain-cmps.sh b/scripts/chain-cmps.sh index 0096bf348..186c9d5bb 100755 --- a/scripts/chain-cmps.sh +++ b/scripts/chain-cmps.sh @@ -1,5 +1,7 @@ -mlrs="mlr5 ~/tmp/miller/mlr ./mlr" -#mlrs="mlr5 ./mlr" +mlrs="mlr" +if [ $# -ge 1 ]; then + mlrs="$@" +fi #reps="1" reps="1 2 3" diff --git a/scripts/chain-lengths.sh b/scripts/chain-lengths.sh index 7647f0671..a584ed738 100755 --- a/scripts/chain-lengths.sh +++ b/scripts/chain-lengths.sh @@ -1,5 +1,7 @@ -mlrs="mlr5 ~/tmp/miller/mlr ./mlr" -#mlrs="mlr5 ./mlr" +mlrs="mlr" +if [ $# -ge 1 ]; then + mlrs="$@" +fi #reps="1" reps="1 2 3" diff --git a/scripts/time-big-files b/scripts/time-big-files index 2e2d3917b..7f761c794 100755 --- a/scripts/time-big-files +++ b/scripts/time-big-files @@ -2,7 +2,10 @@ ourdir=$(dirname $0) -mlrs="mlr5 ~/tmp/miller/mlr ./mlr" +mlrs="mlr" +if [ $# -ge 1 ]; then + mlrs="$@" +fi #mlrs="mlr5 ./mlr" #reps="1"