mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-23 02:14:13 +00:00
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
This commit is contained in:
parent
36f3c3cb0f
commit
b6846fcd0f
19 changed files with 150 additions and 159 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue