From c53077b84835fe71c7ab29b82676cddcff158068 Mon Sep 17 00:00:00 2001 From: refaktor Date: Sat, 23 Mar 2024 11:05:58 +0100 Subject: [PATCH] improvements to spreadsheet, support for raw values, tests don't pass --- env/object.go | 21 ++++++++++-- evaldo/builtins.go | 2 +- evaldo/builtins_spreadsheet.go | 60 +++++++++++++++++++++++----------- 3 files changed, 61 insertions(+), 22 deletions(-) diff --git a/env/object.go b/env/object.go index 2da93aac..8da3e2f3 100644 --- a/env/object.go +++ b/env/object.go @@ -1720,7 +1720,7 @@ func NewList(data []any) *List { return &List{data, Word{0}} } -func RyeToRaw(res Object) any { +func RyeToRaw(res Object) any { // TODO -- MOVE TO UTIL ... provide reverse named symetrically // fmt.Printf("Type: %T", res) switch v := res.(type) { case nil: @@ -1751,7 +1751,7 @@ func NewListFromSeries(block TSeries) List { data := make([]any, block.Len()) for block.Pos() < block.Len() { i := block.Pos() - k1 := block.Pop() + k1 := block.Pop() // TODO -- USE RyeToRaw switch k := k1.(type) { case String: data[i] = k.Value @@ -1766,6 +1766,23 @@ func NewListFromSeries(block TSeries) List { return List{data, Word{0}} } +func NewBlockFromList(list List) TSeries { + data := make([]Object, len(list.Data)) + for i, v := range list.Data { + switch k := v.(type) { + case string: + data[i] = *NewString(k) + case int64: + data[i] = *NewInteger(k) + case float64: + data[i] = *NewDecimal(k) + case List: + data[i] = *NewString("not handeled 3") // TODO -- just temp result + } + } + return *NewTSeries(data) +} + func (i List) Type() Type { return ListType } diff --git a/evaldo/builtins.go b/evaldo/builtins.go index 45c7436e..9dc9c322 100644 --- a/evaldo/builtins.go +++ b/evaldo/builtins.go @@ -681,7 +681,7 @@ var builtins = map[string]*env.Builtin{ }, }, - "get": { // *** currently a concept in testing ... for getting a code of a function, maybe same would be needed for context? + "get_": { // *** find a name or decide on order of naming with generic words clashes with Argsn: 1, Doc: "Returns value of the word in context", Pure: true, diff --git a/evaldo/builtins_spreadsheet.go b/evaldo/builtins_spreadsheet.go index fe29c622..5adef895 100644 --- a/evaldo/builtins_spreadsheet.go +++ b/evaldo/builtins_spreadsheet.go @@ -24,25 +24,34 @@ var Builtins_spreadsheet = map[string]*env.Builtin{ Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { switch header1 := arg0.(type) { case env.Block: + header := header1.Series + cols := make([]string, header.Len()) + for header.Pos() < header.Len() { + i := header.Pos() + k1 := header.Pop() + switch k := k1.(type) { + case env.String: + cols[i] = k.Value + } + } + spr := env.NewSpreadsheet(cols) switch data1 := arg1.(type) { case env.Block: - header := header1.Series - cols := make([]string, header.Len()) - for header.Pos() < header.Len() { - i := header.Pos() - k1 := header.Pop() - switch k := k1.(type) { - case env.String: - cols[i] = k.Value + rdata := data1.Series.S + for _, v := range rdata { + rowd := make([]any, header.Len()) + for ii := 0; ii < header.Len(); ii++ { + rowd[ii] = v } + spr.AddRow(*env.NewSpreadsheetRow(rowd, spr)) } - spr := env.NewSpreadsheet(cols) - data := data1.Series - for data.Pos() < data.Len() { + return *spr + case env.List: + rdata := data1.Data + for _, v := range rdata { rowd := make([]any, header.Len()) for ii := 0; ii < header.Len(); ii++ { - k1 := data.Pop() - rowd[ii] = k1 + rowd[ii] = v } spr.AddRow(*env.NewSpreadsheetRow(rowd, spr)) } @@ -50,6 +59,14 @@ var Builtins_spreadsheet = map[string]*env.Builtin{ default: return MakeArgError(ps, 2, []env.Type{env.BlockType}, "spreadsheet") } + /* for data.Pos() < data.Len() { + rowd := make([]any, header.Len()) + for ii := 0; ii < header.Len(); ii++ { + k1 := data.Pop() + rowd[ii] = k1 + } + spr.AddRow(*env.NewSpreadsheetRow(rowd, spr)) + } */ default: return MakeArgError(ps, 1, []env.Type{env.BlockType}, "spreadsheet") } @@ -1144,15 +1161,20 @@ func GroupBy(ps *env.ProgramState, s env.Spreadsheet, col string, aggregations m if err != nil { return MakeError(ps, fmt.Sprintf("Couldn't retrieve value at row %d (%s)", i, err)) } - groupValStr, ok := groupingVal.(env.String) - if !ok { + var groupValStr string + switch val := groupingVal.(type) { + case env.String: + groupValStr = val.Value + case string: + groupValStr = val + default: return MakeBuiltinError(ps, "Grouping column value must be a string", "group-by") } - if _, ok := aggregatesByGroup[groupValStr.Value]; !ok { - aggregatesByGroup[groupValStr.Value] = make(map[string]float64) + if _, ok := aggregatesByGroup[groupValStr]; !ok { + aggregatesByGroup[groupValStr] = make(map[string]float64) } - groupAggregates := aggregatesByGroup[groupValStr.Value] + groupAggregates := aggregatesByGroup[groupValStr] for aggCol, funs := range aggregations { for _, fun := range funs { @@ -1182,7 +1204,7 @@ func GroupBy(ps *env.ProgramState, s env.Spreadsheet, col string, aggregations m groupAggregates[colAgg] += val case "avg": groupAggregates[colAgg] += val - countByGroup[groupValStr.Value]++ + countByGroup[groupValStr]++ case "min": if min, ok := groupAggregates[colAgg]; !ok || val < min { groupAggregates[colAgg] = val