Skip to content

Commit

Permalink
spreadsheet got where-in, save\csv ... to-decimal
Browse files Browse the repository at this point in the history
  • Loading branch information
refaktor committed Mar 10, 2024
1 parent c9d9193 commit 040eaad
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 10 deletions.
26 changes: 23 additions & 3 deletions evaldo/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,25 @@ var builtins = map[string]*env.Builtin{
},
},

"to-decimal": { // ***
Argsn: 1,
Doc: "Tries to change a Rye value (like string) to integer.",
Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object {
switch addr := arg0.(type) {
case env.String:
floatVal, err := strconv.ParseFloat(addr.Value, 64)

if err != nil {
// Handle the error if the conversion fails (e.g., invalid format)
return MakeBuiltinError(ps, err.Error(), "to-decimal")
}
return *env.NewDecimal(float64(floatVal))
default:
return MakeArgError(ps, 1, []env.Type{env.StringType}, "to-integer")
}
},
},

"to-string": { // ***
Argsn: 1,
Doc: "Tries to turn a Rye value to string.",
Expand Down Expand Up @@ -674,20 +693,21 @@ var builtins = map[string]*env.Builtin{
},
},

"save\\state": {
// TODO -- make save\\context ctx %file
"save\\current": {
Argsn: 0,
Doc: "Saves current state of the program to a file.",
Pure: true,
Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
s := ps.Dump()
fileName := fmt.Sprintf("shell_%s.rye", time.Now().Format("060102_150405"))
fileName := fmt.Sprintf("console_%s.rye", time.Now().Format("060102_150405"))

err := os.WriteFile(fileName, []byte(s), 0600)
if err != nil {
ps.FailureFlag = true
return MakeBuiltinError(ps, fmt.Sprintf("error writing state: %s", err.Error()), "save\\state")
}
fmt.Println("State saved to \033[1m" + fileName + "\033[0m.")
fmt.Println("State current context to \033[1m" + fileName + "\033[0m.")
return *env.NewInteger(1)
},
},
Expand Down
142 changes: 137 additions & 5 deletions evaldo/builtins_spreadsheet.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package evaldo

import (
"encoding/csv"
"fmt"
"os"
"regexp"
"slices"
Expand All @@ -12,6 +13,7 @@ import (
"strings"

"github.com/refaktor/rye/env"
"github.com/refaktor/rye/util"
)

var Builtins_spreadsheet = map[string]*env.Builtin{
Expand Down Expand Up @@ -188,6 +190,62 @@ var Builtins_spreadsheet = map[string]*env.Builtin{
}
},
},
"save\\csv": {
Argsn: 2,
Doc: "Saves a spreadsheet to a .csv file.",
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 file := arg1.(type) {
case env.Uri:
// rows, err := db1.Value.(*sql.DB).Query(sqlstr, vals...)
f, err := os.Create(file.GetPath())
if err != nil {
// log.Fatal("Unable to read input file "+filePath, err)
return MakeBuiltinError(ps, "Unable to create input file.", "save\\csv")
}
defer f.Close()

cLen := len(spr.Cols)

csvWriter := csv.NewWriter(f)

err1 := csvWriter.Write(spr.Cols)
if err1 != nil {
return MakeBuiltinError(ps, "Unable to create write header.", "save\\csv")
}

for ir, row := range spr.Rows {
strVals := make([]string, cLen)
// TODO -- just adhoc ... move to a general function in utils RyeValsToString or something like it
for i, v := range row.Values {
var sv string
switch tv := v.(type) {
case env.String:
sv = tv.Value
case env.Integer:
sv = strconv.Itoa(int(tv.Value))
case env.Decimal:
sv = fmt.Sprintf("%f", tv.Value)
}
strVals[i] = sv
}
err := csvWriter.Write(strVals)
if err != nil {
return MakeBuiltinError(ps, "Unable to write line: "+strconv.Itoa(int(ir)), "save\\csv")
}
}
csvWriter.Flush()
f.Close()
return spr
default:
return MakeArgError(ps, 1, []env.Type{env.UriType}, "save\\csv")
}
default:
return MakeArgError(ps, 1, []env.Type{env.UriType}, "save\\csv")
}
},
},
"where-equal": {
Argsn: 3,
Doc: "Returns spreadsheet of rows where specific colum is equal to given value.",
Expand Down Expand Up @@ -245,9 +303,33 @@ var Builtins_spreadsheet = map[string]*env.Builtin{
case env.String:
switch col := arg1.(type) {
case env.Word:
return WhereContains(ps, spr, ps.Idx.GetWord(col.Index), s.Value)
return WhereContains(ps, spr, ps.Idx.GetWord(col.Index), s.Value, false)
case env.String:
return WhereContains(ps, spr, col.Value, s.Value, false)
default:
return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-contains")
}
default:
return MakeArgError(ps, 3, []env.Type{env.StringType}, "where-contains")
}
default:
return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "where-contains")
}
},
},
"where-not-contains": {
Argsn: 3,
Doc: "Returns spreadsheet of rows where specific colum contains a given string value.",
Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
switch spr := arg0.(type) {
case env.Spreadsheet:
switch s := arg2.(type) {
case env.String:
switch col := arg1.(type) {
case env.Word:
return WhereContains(ps, spr, ps.Idx.GetWord(col.Index), s.Value, true)
case env.String:
return WhereContains(ps, spr, col.Value, s.Value)
return WhereContains(ps, spr, col.Value, s.Value, true)
default:
return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-contains")
}
Expand Down Expand Up @@ -316,6 +398,30 @@ var Builtins_spreadsheet = map[string]*env.Builtin{
}
},
},
"where-in": {
Argsn: 3,
Doc: "Returns spreadsheet of rows where specific colum value if found in block of values.",
Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) (res env.Object) {
switch spr := arg0.(type) {
case env.Spreadsheet:
switch s := arg2.(type) {
case env.Block:
switch col := arg1.(type) {
case env.Word:
return WhereIn(ps, spr, ps.Idx.GetWord(col.Index), s.Series.S)
case env.String:
return WhereIn(ps, spr, col.Value, s.Series.S)
default:
return MakeArgError(ps, 2, []env.Type{env.WordType, env.StringType}, "where-in")
}
default:
return MakeArgError(ps, 3, []env.Type{env.StringType}, "where-in")
}
default:
return MakeArgError(ps, 1, []env.Type{env.SpreadsheetType}, "where-in")
}
},
},
"limit": {
Argsn: 2,
Doc: "Returns spreadsheet with number of rows limited to second argument.",
Expand Down Expand Up @@ -672,16 +778,22 @@ func WhereMatch(ps *env.ProgramState, s env.Spreadsheet, name string, r *regexp.
}
}

func WhereContains(ps *env.ProgramState, s env.Spreadsheet, name string, val string) env.Object {
func WhereContains(ps *env.ProgramState, s env.Spreadsheet, name string, val string, not bool) env.Object {
idx := slices.Index(s.Cols, name)
nspr := env.NewSpreadsheet(s.Cols)
if idx > -1 {
for _, row := range s.Rows {
if len(row.Values) > idx {
rv := row.Values[idx]
if rvStr, ok := rv.(env.String); ok {
if strings.Contains(rvStr.Value, val) {
nspr.AddRow(row)
if !not {
if strings.Contains(rvStr.Value, val) {
nspr.AddRow(row)
}
} else {
if !strings.Contains(rvStr.Value, val) {
nspr.AddRow(row)
}
}
}
}
Expand All @@ -692,6 +804,26 @@ func WhereContains(ps *env.ProgramState, s env.Spreadsheet, name string, val str
}
}

func WhereIn(ps *env.ProgramState, s env.Spreadsheet, name string, b []env.Object) env.Object {
idx := slices.Index(s.Cols, name)
nspr := env.NewSpreadsheet(s.Cols)
if idx > -1 {
for _, row := range s.Rows {
if len(row.Values) > idx {
rv := row.Values[idx]
if rvObj, ok := rv.(env.Object); ok {
if util.ContainsVal(ps, b, rvObj) {
nspr.AddRow(row)
}
}
}
}
return *nspr
} else {
return MakeBuiltinError(ps, "Column not found.", "WhereIn")
}
}

func WhereGreater(ps *env.ProgramState, s env.Spreadsheet, name string, val env.Object) env.Object {
idx := slices.Index(s.Cols, name)
nspr := env.NewSpreadsheet(s.Cols)
Expand Down
3 changes: 1 addition & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,11 @@ func findLastConsoleSave() string {

files := make([]string, 0)

// Filter files starting with "shell_"
for _, entry := range entries {
if entry.IsDir() {
continue // Skip directories
}
if strings.HasPrefix(entry.Name(), "shell_") {
if strings.HasPrefix(entry.Name(), "console_") {
files = append(files, entry.Name())
}
}
Expand Down

0 comments on commit 040eaad

Please sign in to comment.