From aa21a537914afceb028341008b9c64a35bf865d3 Mon Sep 17 00:00:00 2001 From: William Bell Date: Mon, 17 Jul 2023 20:52:42 +0100 Subject: [PATCH] add more features --- src/buffer.go | 145 +++++++++++++++++++++++++++++++++++++++++++++++++ src/file.go | 29 ++++++++-- src/path.go | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/string.go | 21 ++++++++ 4 files changed, 338 insertions(+), 3 deletions(-) diff --git a/src/buffer.go b/src/buffer.go index e35aef0..4624706 100644 --- a/src/buffer.go +++ b/src/buffer.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "fmt" ) @@ -150,6 +151,150 @@ func ArBuffer(buf []byte) ArObject { return obj, ArErr{} }, } + obj.obj["splitN"] = builtinFunc{ + "splitN", + func(a ...any) (any, ArErr) { + if len(a) != 2 { + return nil, ArErr{ + TYPE: "TypeError", + message: "expected 1 argument, got " + fmt.Sprint(len(a)), + EXISTS: true, + } + } + splitVal := ArValidToAny(a[0]) + if typeof(splitVal) != "buffer" { + return nil, ArErr{ + TYPE: "TypeError", + message: "expected buffer, got " + typeof(splitVal), + EXISTS: true, + } + } + var separator = splitVal.([]byte) + nVal := ArValidToAny(a[1]) + if typeof(nVal) != "number" { + return nil, ArErr{ + TYPE: "TypeError", + message: "expected number, got " + typeof(nVal), + EXISTS: true, + } + } + nNum := nVal.(number) + if nNum.Denom().Cmp(one.Denom()) != 0 { + return nil, ArErr{ + TYPE: "TypeError", + message: "expected integer, got " + fmt.Sprint(nNum), + EXISTS: true, + } + } + n := nNum.Num().Int64() + var result [][]byte + start := 0 + var i int64 + for i = 0; i < n; i++ { + index := bytes.Index(buf[start:], separator) + if index == -1 { + result = append(result, buf[start:]) + break + } + end := start + index + result = append(result, buf[start:end]) + start = end + len(separator) + } + + if int64(len(result)) != n { + result = append(result, buf[start:]) + } + var bufoutput = []any{} + for _, v := range result { + bufoutput = append(bufoutput, ArBuffer(v)) + } + return ArArray(bufoutput), ArErr{} + }, + } + obj.obj["split"] = builtinFunc{ + "split", + func(a ...any) (any, ArErr) { + if len(a) != 1 { + return nil, ArErr{ + TYPE: "TypeError", + message: "expected 1 argument, got " + fmt.Sprint(len(a)), + EXISTS: true, + } + } + splitVal := ArValidToAny(a[0]) + if typeof(splitVal) != "buffer" { + return nil, ArErr{ + TYPE: "TypeError", + message: "expected buffer, got " + typeof(splitVal), + EXISTS: true, + } + } + var separator = splitVal.([]byte) + var result [][]byte + start := 0 + + for { + index := bytes.Index(buf[start:], separator) + if index == -1 { + result = append(result, buf[start:]) + break + } + end := start + index + result = append(result, buf[start:end]) + start = end + len(separator) + } + var bufoutput = []any{} + for _, v := range result { + bufoutput = append(bufoutput, ArBuffer(v)) + } + return ArArray(bufoutput), ArErr{} + }, + } + obj.obj["slice"] = builtinFunc{ + "slice", + func(a ...any) (any, ArErr) { + if len(a) != 2 { + return nil, ArErr{ + TYPE: "TypeError", + message: "expected 2 arguments, got " + fmt.Sprint(len(a)), + EXISTS: true, + } + } + startVal := ArValidToAny(a[0]) + if typeof(startVal) != "number" { + return nil, ArErr{ + TYPE: "TypeError", + message: "expected number, got " + typeof(startVal), + EXISTS: true, + } + } + start := startVal.(number) + if start.Denom().Cmp(one.Denom()) != 0 { + return nil, ArErr{ + TYPE: "TypeError", + message: "expected integer, got " + fmt.Sprint(start), + EXISTS: true, + } + } + endVal := ArValidToAny(a[1]) + if typeof(endVal) != "number" { + return nil, ArErr{ + TYPE: "TypeError", + message: "expected number, got " + typeof(endVal), + EXISTS: true, + } + } + end := endVal.(number) + if end.Denom().Cmp(one.Denom()) != 0 { + return nil, ArErr{ + TYPE: "TypeError", + message: "expected integer, got " + fmt.Sprint(end), + EXISTS: true, + } + } + return ArBuffer(buf[floor(start).Num().Int64():floor(end).Num().Int64()]), ArErr{} + }, + } obj.obj["to"] = builtinFunc{ "to", func(a ...any) (any, ArErr) { diff --git a/src/file.go b/src/file.go index 5f537db..856e924 100644 --- a/src/file.go +++ b/src/file.go @@ -123,6 +123,13 @@ func ArRead(args ...any) (any, ArErr) { } return ArTimeClass(info.ModTime()), ArErr{} }}, + "close": builtinFunc{"close", func(...any) (any, ArErr) { + err := file.Close() + if err != nil { + return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true} + } + return nil, ArErr{} + }}, }), ArErr{} } @@ -148,7 +155,10 @@ func ArWrite(args ...any) (any, ArErr) { return ArObject{}, ArErr{TYPE: "Runtime Error", message: "text takes a string not type '" + typeof(args[0]) + "'", EXISTS: true} } args[0] = ArValidToAny(args[0]) - file.Write([]byte(args[0].(string))) + _, err = file.Write([]byte(args[0].(string))) + if err != nil { + return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true} + } return nil, ArErr{} }}, "buffer": builtinFunc{"buffer", func(args ...any) (any, ArErr) { @@ -159,7 +169,10 @@ func ArWrite(args ...any) (any, ArErr) { return ArObject{}, ArErr{TYPE: "Runtime Error", message: "buffer takes a buffer not type '" + typeof(args[0]) + "'", EXISTS: true} } args[0] = ArValidToAny(args[0]) - file.Write(args[0].([]byte)) + _, err = file.Write(args[0].([]byte)) + if err != nil { + return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true} + } return nil, ArErr{} }}, "json": builtinFunc{"json", func(args ...any) (any, ArErr) { @@ -170,7 +183,17 @@ func ArWrite(args ...any) (any, ArErr) { if err != nil { return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true} } - file.Write([]byte(jsonstr)) + _, err = file.Write([]byte(jsonstr)) + if err != nil { + return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true} + } + return nil, ArErr{} + }}, + "close": builtinFunc{"close", func(...any) (any, ArErr) { + err := file.Close() + if err != nil { + return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true} + } return nil, ArErr{} }}, }), ArErr{} diff --git a/src/path.go b/src/path.go index 44e48ed..61f4e2e 100644 --- a/src/path.go +++ b/src/path.go @@ -41,6 +41,152 @@ var ArPath = Map( } return ret, ArErr{} }}, + "exists": builtinFunc{ + "exists", + func(args ...any) (any, ArErr) { + if len(args) != 1 { + return nil, ArErr{ + TYPE: "runtime", + message: "exists takes exactly 1 argument, got " + fmt.Sprint(len(args)), + EXISTS: true, + } + } + args[0] = ArValidToAny(args[0]) + if typeof(args[0]) != "string" { + return nil, ArErr{ + TYPE: "runtime", + message: "exists argument must be a string, got " + typeof(args[0]), + EXISTS: true, + } + } + _, err := os.Stat(args[0].(string)) + if err != nil { + if os.IsNotExist(err) { + return false, ArErr{} + } + return nil, ArErr{ + TYPE: "runtime", + message: err.Error(), + EXISTS: true, + } + } + return true, ArErr{} + }}, + "mkAllDir": builtinFunc{ + "mkAllDir", + func(args ...any) (any, ArErr) { + if len(args) != 1 { + return nil, ArErr{ + TYPE: "runtime", + message: "mkAllDir takes exactly 1 argument, got " + fmt.Sprint(len(args)), + EXISTS: true, + } + } + args[0] = ArValidToAny(args[0]) + if typeof(args[0]) != "string" { + return nil, ArErr{ + TYPE: "runtime", + message: "mkAllDir argument must be a string, got " + typeof(args[0]), + EXISTS: true, + } + } + err := os.MkdirAll(args[0].(string), os.ModePerm) + if err != nil { + return nil, ArErr{ + TYPE: "runtime", + message: err.Error(), + EXISTS: true, + } + } + return nil, ArErr{} + }}, + "mkDir": builtinFunc{ + "mkDir", + func(args ...any) (any, ArErr) { + if len(args) != 1 { + return nil, ArErr{ + TYPE: "runtime", + message: "mkDir takes exactly 1 argument, got " + fmt.Sprint(len(args)), + EXISTS: true, + } + } + args[0] = ArValidToAny(args[0]) + if typeof(args[0]) != "string" { + return nil, ArErr{ + TYPE: "runtime", + message: "mkDir argument must be a string, got " + typeof(args[0]), + EXISTS: true, + } + } + err := os.Mkdir(args[0].(string), os.ModePerm) + if err != nil { + return nil, ArErr{ + TYPE: "runtime", + message: err.Error(), + EXISTS: true, + } + } + return nil, ArErr{} + }}, + "remove": builtinFunc{ + "remove", + func(args ...any) (any, ArErr) { + if len(args) != 1 { + return nil, ArErr{ + TYPE: "runtime", + message: "remove takes exactly 1 argument, got " + fmt.Sprint(len(args)), + EXISTS: true, + } + } + args[0] = ArValidToAny(args[0]) + if typeof(args[0]) != "string" { + return nil, ArErr{ + TYPE: "runtime", + message: "remove argument must be a string, got " + typeof(args[0]), + EXISTS: true, + } + } + err := os.Remove(args[0].(string)) + if err != nil { + return nil, ArErr{ + TYPE: "runtime", + message: err.Error(), + EXISTS: true, + } + } + return nil, ArErr{} + }}, + "isDir": builtinFunc{ + "isDir", + func(args ...any) (any, ArErr) { + if len(args) != 1 { + return nil, ArErr{ + TYPE: "runtime", + message: "isDir takes exactly 1 argument, got " + fmt.Sprint(len(args)), + EXISTS: true, + } + } + args[0] = ArValidToAny(args[0]) + if typeof(args[0]) != "string" { + return nil, ArErr{ + TYPE: "runtime", + message: "isDir argument must be a string, got " + typeof(args[0]), + EXISTS: true, + } + } + stat, err := os.Stat(args[0].(string)) + if err != nil { + if os.IsNotExist(err) { + return false, ArErr{} + } + return nil, ArErr{ + TYPE: "runtime", + message: err.Error(), + EXISTS: true, + } + } + return stat.IsDir(), ArErr{} + }}, "join": builtinFunc{ "join", func(args ...any) (any, ArErr) { diff --git a/src/string.go b/src/string.go index 4864cef..430edac 100644 --- a/src/string.go +++ b/src/string.go @@ -262,6 +262,27 @@ func ArString(str string) ArObject { } return output, ArErr{} }} + obj.obj["splitN"] = builtinFunc{ + "splitN", + func(a ...any) (any, ArErr) { + if len(a) != 2 { + return nil, ArErr{"TypeError", "expected 2 or more argument, got " + fmt.Sprint(len(a)), 0, "", "", true} + } + if typeof(a[0]) != "string" { + return nil, ArErr{"TypeError", "expected string, got " + typeof(a[0]), 0, "", "", true} + } + if typeof(a[1]) != "number" || !a[1].(number).IsInt() { + return nil, ArErr{"TypeError", "expected integer, got " + typeof(a[1]), 0, "", "", true} + } + splitby := ArValidToAny(a[0]).(string) + n := int(a[1].(number).Num().Int64()) + output := []any{} + splitted := (strings.SplitN(str, splitby, n)) + for _, v := range splitted { + output = append(output, ArString(v)) + } + return output, ArErr{} + }} obj.obj["capitalise"] = builtinFunc{ "capitalise", func(a ...any) (any, ArErr) {