From a41c33dd282b12d160320235497d3375ab356f94 Mon Sep 17 00:00:00 2001 From: Andrew Owen Date: Fri, 20 Sep 2024 21:17:07 -0600 Subject: [PATCH 1/2] clean up add-column! errors --- evaldo/builtins_spreadsheet.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/evaldo/builtins_spreadsheet.go b/evaldo/builtins_spreadsheet.go index 4ff48c2a..45665182 100644 --- a/evaldo/builtins_spreadsheet.go +++ b/evaldo/builtins_spreadsheet.go @@ -635,25 +635,25 @@ var Builtins_spreadsheet = map[string]*env.Builtin{ case env.Block: return GenerateColumn(ps, spr, newCol, fromCols, code) default: - return MakeArgError(ps, 4, []env.Type{env.BlockType}, "add-col!") + return MakeArgError(ps, 4, []env.Type{env.BlockType}, "add-column!") } case env.Word: switch replaceBlock := arg3.(type) { case env.Block: if replaceBlock.Series.Len() != 2 { - return MakeBuiltinError(ps, "Replacement block must contain a regex object and replacement string.", "add-col!") + return MakeBuiltinError(ps, "Replacement block must contain a regex object and replacement string.", "add-column!") } regexNative, ok := replaceBlock.Series.S[0].(env.Native) if !ok { - return MakeBuiltinError(ps, "First element of replacement block must be a regex object.", "add-col!") + return MakeBuiltinError(ps, "First element of replacement block must be a regex object.", "add-column!") } regex, ok := regexNative.Value.(*regexp.Regexp) if !ok { - return MakeBuiltinError(ps, "First element of replacement block must be a regex object.", "add-col!") + return MakeBuiltinError(ps, "First element of replacement block must be a regex object.", "add-column!") } replaceStr, ok := replaceBlock.Series.S[1].(env.String) if !ok { - return MakeBuiltinError(ps, "Second element of replacement block must be a string.", "add-col!") + return MakeBuiltinError(ps, "Second element of replacement block must be a string.", "add-column!") } err := GenerateColumnRegexReplace(ps, &spr, newCol, fromCols, regex, replaceStr.Value) if err != nil { @@ -661,16 +661,16 @@ var Builtins_spreadsheet = map[string]*env.Builtin{ } return spr default: - return MakeArgError(ps, 3, []env.Type{env.BlockType}, "add-col!") + return MakeArgError(ps, 3, []env.Type{env.BlockType}, "add-column!") } default: - return MakeArgError(ps, 3, []env.Type{env.BlockType}, "add-col!") + return MakeArgError(ps, 3, []env.Type{env.BlockType}, "add-column!") } default: - return MakeArgError(ps, 2, []env.Type{env.WordType}, "add-col!") + return MakeArgError(ps, 2, []env.Type{env.WordType}, "add-column!") } default: - return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "add-col!") + return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "add-column!") } }, }, From bfa6dc7a88dafb37819ca1391135642e90919343 Mon Sep 17 00:00:00 2001 From: Andrew Owen Date: Fri, 20 Sep 2024 22:32:35 -0600 Subject: [PATCH 2/2] Add thaw, and functions that rely on having a mutable spreadsheet --- env/spreadsheet.go | 4 ++ evaldo/builtins.go | 16 ++++++++ evaldo/builtins_spreadsheet.go | 52 +++++++++++++++++++++++++- examples/spreadsheet/in-place-mods.rye | 18 +++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 examples/spreadsheet/in-place-mods.rye diff --git a/env/spreadsheet.go b/env/spreadsheet.go index 20b6f8b6..435da6d2 100644 --- a/env/spreadsheet.go +++ b/env/spreadsheet.go @@ -48,6 +48,10 @@ func (s *Spreadsheet) AddRow(vals SpreadsheetRow) { s.Rows = append(s.Rows, vals) } +func (s *Spreadsheet) RemoveRowByIndex(index int64) { + s.Rows = append(s.Rows[:index], s.Rows[index+1:]...) +} + func (s *Spreadsheet) GetRows() []SpreadsheetRow { return s.Rows } diff --git a/evaldo/builtins.go b/evaldo/builtins.go index 50af087f..f252717d 100644 --- a/evaldo/builtins.go +++ b/evaldo/builtins.go @@ -803,6 +803,22 @@ var builtins = map[string]*env.Builtin{ }, }, + "thaw": { + Argsn: 1, + Doc: "Makes a value (currently only spreadsheets) mutable instead of immutable", + Pure: true, + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch sp := arg0.(type) { + case env.Spreadsheet: + return &sp + case *env.Spreadsheet: + return sp + default: + return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "thaw") + } + }, + }, + "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", diff --git a/evaldo/builtins_spreadsheet.go b/evaldo/builtins_spreadsheet.go index 45665182..0640a7a3 100644 --- a/evaldo/builtins_spreadsheet.go +++ b/evaldo/builtins_spreadsheet.go @@ -204,6 +204,54 @@ var Builtins_spreadsheet = map[string]*env.Builtin{ }, }, + "add-rows!": { + Argsn: 2, + Doc: "Add one or more rows to a spreadsheet", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch spr := arg0.(type) { + case *env.Spreadsheet: + switch data1 := arg1.(type) { + case env.Block: + data := data1.Series + for data.Pos() < data.Len() { + rowd := make([]any, len(spr.Cols)) + for ii := 0; ii < len(spr.Cols); ii++ { + k1 := data.Pop() + rowd[ii] = k1 + } + spr.AddRow(*env.NewSpreadsheetRow(rowd, spr)) + } + return spr + case env.Native: + spr.Rows = append(spr.Rows, data1.Value.([]env.SpreadsheetRow)...) + return spr + default: + return MakeArgError(ps, 2, []env.Type{env.BlockType, env.NativeType}, "add-rows!") + } + default: + return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "add-rows!") + } + }, + }, + "remove-row!": { + Argsn: 2, + Doc: "Remove a row from a spreadsheet by index", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch spr := arg0.(type) { + case *env.Spreadsheet: + switch data1 := arg1.(type) { + case env.Integer: + spr.RemoveRowByIndex(data1.Value) + return spr + default: + return MakeArgError(ps, 2, []env.Type{env.BlockType, env.NativeType}, "remove-row!") + } + default: + return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "remove-row!") + } + }, + }, + // TODO 2 -- this could move to a go function so it could be called by general load that uses extension to define the loader "load\\csv": { Argsn: 1, @@ -577,10 +625,12 @@ var Builtins_spreadsheet = map[string]*env.Builtin{ Doc: "Gets the column names (header) as block.", Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { switch spr := arg0.(type) { + case *env.Spreadsheet: + return spr.GetColumns() case env.Spreadsheet: return spr.GetColumns() default: - return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "columns?") + return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "headers?") } }, }, diff --git a/examples/spreadsheet/in-place-mods.rye b/examples/spreadsheet/in-place-mods.rye new file mode 100644 index 00000000..85b6a822 --- /dev/null +++ b/examples/spreadsheet/in-place-mods.rye @@ -0,0 +1,18 @@ +; Create a spreadsheet + +deliveries: thaw spreadsheet { "street" "city" "zip" "contents" } +[ + "Maple" "Onowa" "55555" "A bottle of Maple Syrup" + "Oak" "Springfield" "11111" "A donut-shaped stuffed animal" + "Acorn" "Springfield" "11112" "A handheld fan" + "Birch" "Springfield" "11112" "A laptop" +] + +deliveries .to-json |print +print "" +deliveries |add-rows! [ "Vega" "Bayton" "12345" "A Nova" ] +deliveries .to-json |print +print "" +deliveries |remove-row! 1 +deliveries .to-json |print +print "" \ No newline at end of file