add subprocess

This commit is contained in:
2023-03-21 23:03:25 +00:00
parent 54ea92886e
commit 4f3d419c28
12 changed files with 202 additions and 146 deletions

1
.gitignore vendored
View File

@@ -1,2 +1 @@
node_modules
bin bin

8
go.mod
View File

@@ -8,12 +8,10 @@ require (
) )
require ( require (
github.com/jwalton/go-supportscolor v1.1.0 // indirect github.com/jwalton/go-supportscolor v1.1.0
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-isatty v0.0.17 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.6.0 // indirect golang.org/x/term v0.6.0
golang.org/x/text v0.8.0 // indirect golang.org/x/text v0.8.0
) )

View File

@@ -68,7 +68,7 @@ func ArArray(arr []any) ArObject {
// a[0] is start // a[0] is start
// a[1] is end // a[1] is end
// a[2] is step // a[2] is step
if len(a) < 0 || len(a) > 3 { if len(a) > 3 {
return nil, ArErr{"TypeError", "expected 1 to 3 arguments, got " + fmt.Sprint(len(a)), 0, "", "", true} return nil, ArErr{"TypeError", "expected 1 to 3 arguments, got " + fmt.Sprint(len(a)), 0, "", "", true}
} }
var ( var (

View File

@@ -24,7 +24,6 @@ func anyToBool(x any) bool {
default: default:
return true return true
} }
} }
var booleanCompile = makeRegex(`( )*(true|false|null)( )*`) var booleanCompile = makeRegex(`( )*(true|false|null)( )*`)

View File

@@ -12,16 +12,6 @@ type builtinFunc struct {
func ArgonString(args ...any) (any, ArErr) { func ArgonString(args ...any) (any, ArErr) {
return ArString(anyToArgon(args[0], true, false, 3, 0, false, 0)), ArErr{} return ArString(anyToArgon(args[0], true, false, 3, 0, false, 0)), ArErr{}
} }
func ArgonPassworInput(args ...any) (any, ArErr) {
resp, err := getPassword(args...)
if err != nil {
return nil, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
}
return ArString(resp), ArErr{}
}
func ArgonInput(args ...any) (any, ArErr) {
return input(args...), ArErr{}
}
func ArgonNumber(args ...any) (any, ArErr) { func ArgonNumber(args ...any) (any, ArErr) {
if len(args) == 0 { if len(args) == 0 {

View File

@@ -7,8 +7,6 @@ var vars = Map(anymap{})
func init() { func init() {
vars.obj["global"] = vars vars.obj["global"] = vars
vars.obj["term"] = ArTerm vars.obj["term"] = ArTerm
vars.obj["input"] = builtinFunc{"input", ArgonInput}
vars.obj["passwordInput"] = builtinFunc{"passwordInput", ArgonPassworInput}
vars.obj["number"] = builtinFunc{"number", ArgonNumber} vars.obj["number"] = builtinFunc{"number", ArgonNumber}
vars.obj["string"] = builtinFunc{"string", ArgonString} vars.obj["string"] = builtinFunc{"string", ArgonString}
vars.obj["infinity"] = infinity vars.obj["infinity"] = infinity
@@ -151,4 +149,5 @@ func init() {
} }
return ArArray([]any{}), ArErr{} return ArArray([]any{}), ArErr{}
}} }}
vars.obj["subprocess"] = builtinFunc{"subprocess", ArSubprocess}
} }

View File

@@ -165,94 +165,3 @@ func isUnhashable(val any) bool {
keytype := typeof(val) keytype := typeof(val)
return keytype == "array" || keytype == "map" return keytype == "array" || keytype == "map"
} }
func getFromArArray(m ArObject, r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
var (
start int = 0
end any = nil
step int = 1
)
{
startval, err := runVal(r.args[0], stack, stacklevel+1)
if err.EXISTS {
return ArObject{}, err
}
if startval == nil {
start = 0
} else if typeof(startval) != "number" || !startval.(number).IsInt() {
return ArObject{}, ArErr{
"TypeError",
"slice index must be an integer",
r.line,
r.path,
r.code,
true,
}
} else {
start = int(startval.(number).Num().Int64())
}
}
if len(r.args) > 1 {
endval, err := runVal(r.args[1], stack, stacklevel+1)
if err.EXISTS {
return ArObject{}, err
}
if endval == nil {
end = m.obj["length"]
} else if typeof(endval) != "number" && !endval.(number).IsInt() {
return ArObject{}, ArErr{
"TypeError",
"slice ending index must be an integer",
r.line,
r.path,
r.code,
true,
}
} else {
end = int(endval.(number).Num().Int64())
}
}
if len(r.args) > 2 {
stepval, err := runVal(r.args[2], stack, stacklevel+1)
if err.EXISTS {
return ArObject{}, err
}
if stepval == nil {
step = 1
} else if typeof(stepval) != "number" && !stepval.(number).IsInt() {
return ArObject{}, ArErr{
"TypeError",
"slice step must be an integer",
r.line,
r.path,
r.code,
true,
}
} else {
step = int(stepval.(number).Num().Int64())
}
}
if start < 0 {
start = m.obj["length"].(int) + start
}
if _, ok := end.(int); ok && end.(int) < 0 {
end = m.obj["length"].(int) + end.(int)
}
if end == nil {
return m.obj["__value__"].([]any)[start], ArErr{}
} else if step == 1 {
return ArArray([]any{m.obj["__value__"].([]any)[start:end.(int)]}), ArErr{}
} else {
output := []any{}
if step > 0 {
for i := start; i < end.(int); i += step {
output = append(output, m.obj["__value__"].([]any)[i])
}
} else {
for i := end.(int) - 1; i >= start; i += step {
output = append(output, m.obj["__value__"].([]any)[i])
}
}
return ArArray(output), ArErr{}
}
}

View File

@@ -42,11 +42,11 @@ func getPassword(args ...any) (string, error) {
break break
} }
if char[0] == 3 || char[0] == 4 { if char[0] == 3 || char[0] == 4 {
return "", fmt.Errorf("User cancelled") return "", fmt.Errorf("keyboard interupt")
} else if char[0] == '\r' || char[0] == '\n' { } else if char[0] == '\r' || char[0] == '\n' {
fmt.Println() fmt.Println()
break break
} else if char[0] == '\b' { } else if char[0] == '\b' || char[0] == 127 {
if len(password) > 0 { if len(password) > 0 {
password = password[:len(password)-1] password = password[:len(password)-1]
fmt.Print("\b \b") fmt.Print("\b \b")

View File

@@ -4,6 +4,9 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
"golang.org/x/text/cases"
"golang.org/x/text/language"
) )
var stringCompile = makeRegex("(( *)\"((\\\\([a-z\\\"'`]))|[^\\\"])*\"( *))|(( *)'((\\\\([a-z\\'\"`]))|[^\\'])*'( *))") var stringCompile = makeRegex("(( *)\"((\\\\([a-z\\\"'`]))|[^\\\"])*\"( *))|(( *)'((\\\\([a-z\\'\"`]))|[^\\'])*'( *))")
@@ -88,7 +91,7 @@ func ArString(str string) ArObject {
// a[0] is start // a[0] is start
// a[1] is end // a[1] is end
// a[2] is step // a[2] is step
if len(a) < 0 || len(a) > 3 { if len(a) > 3 {
return nil, ArErr{"TypeError", "expected 1 to 3 arguments, got " + fmt.Sprint(len(a)), 0, "", "", true} return nil, ArErr{"TypeError", "expected 1 to 3 arguments, got " + fmt.Sprint(len(a)), 0, "", "", true}
} }
var ( var (
@@ -265,7 +268,7 @@ func ArString(str string) ArObject {
if len(a) != 0 { if len(a) != 0 {
return nil, ArErr{"TypeError", "expected 0 arguments, got " + fmt.Sprint(len(a)), 0, "", "", true} return nil, ArErr{"TypeError", "expected 0 arguments, got " + fmt.Sprint(len(a)), 0, "", "", true}
} }
return strings.Title(str), ArErr{} return cases.Title(language.English).String(str), ArErr{}
}} }}
obj.obj["lower"] = builtinFunc{ obj.obj["lower"] = builtinFunc{
"lower", "lower",

139
src/subprocess.go Normal file
View File

@@ -0,0 +1,139 @@
package main
import (
"bufio"
"fmt"
"os/exec"
)
func ArSubprocess(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "RuntimeError",
message: fmt.Sprintf("subprocess() takes exactly 1 argument (%d given)", len(args)),
EXISTS: true,
}
} else if typeof(args[0]) != "array" {
fmt.Println(args[0])
return nil, ArErr{
TYPE: "TypeError",
message: fmt.Sprintf("subprocess() argument must be an array, not %s", typeof(args[0])),
EXISTS: true,
}
} else if len(args[0].([]any)) == 0 {
return nil, ArErr{
TYPE: "RuntimeError",
message: "subprocess() argument must be an array of strings, not an empty array",
EXISTS: true,
}
}
commandlist := []string{}
for _, x := range args[0].([]any) {
if typeof(x) != "string" {
return nil, ArErr{
TYPE: "TypeError",
message: fmt.Sprintf("subprocess() argument must be an array of strings, not %s", typeof(x)),
EXISTS: true,
}
}
commandlist = append(commandlist, x.(ArObject).obj["__value__"].(string))
}
cmd := exec.Command(commandlist[0], commandlist[1:]...)
return Map(
anymap{
"stdout": builtinFunc{
"output",
func(args ...any) (any, ArErr) {
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, ArErr{
TYPE: "RuntimeError",
message: err.Error(),
EXISTS: true,
}
}
if err := cmd.Start(); err != nil {
return nil, ArErr{
TYPE: "RuntimeError",
message: err.Error(),
EXISTS: true,
}
}
scanner := bufio.NewScanner(stdout) // create a new scanner to read the output
scanner.Split(bufio.ScanRunes)
return Map(anymap{
"scan": builtinFunc{
"scan",
func(args ...any) (any, ArErr) {
if len(args) != 0 {
return nil, ArErr{
TYPE: "TypeError",
message: fmt.Sprintf("scan() takes exactly 0 arguments (%d given)", len(args)),
EXISTS: true,
}
}
return scanner.Scan(), ArErr{}
}},
"text": builtinFunc{
"text",
func(args ...any) (any, ArErr) {
if len(args) != 0 {
return nil, ArErr{
TYPE: "TypeError",
message: fmt.Sprintf("text() takes exactly 0 arguments (%d given)", len(args)),
EXISTS: true,
}
}
return scanner.Text(), ArErr{}
}},
"err": builtinFunc{
"err",
func(args ...any) (any, ArErr) {
if len(args) != 0 {
return nil, ArErr{
TYPE: "TypeError",
message: fmt.Sprintf("err() takes exactly 0 arguments (%d given)", len(args)),
EXISTS: true,
}
}
if err := scanner.Err(); err != nil {
return err.Error(), ArErr{}
}
return nil, ArErr{}
}},
"wait": builtinFunc{
"wait",
func(args ...any) (any, ArErr) {
if len(args) != 0 {
return nil, ArErr{
TYPE: "TypeError",
message: fmt.Sprintf("wait() takes exactly 0 arguments (%d given)", len(args)),
EXISTS: true,
}
}
if err := cmd.Wait(); err != nil {
return err.Error(), ArErr{}
}
return nil, ArErr{}
},
},
}), ArErr{}
}},
"output": builtinFunc{
"output",
func(args ...any) (any, ArErr) {
out, err := cmd.Output()
if err != nil {
return nil, ArErr{
TYPE: "RuntimeError",
message: err.Error(),
EXISTS: true,
}
}
return string(out), ArErr{}
}},
},
), ArErr{}
}

View File

@@ -7,33 +7,6 @@ import (
var timing = anymap{} var timing = anymap{}
var plain = Map(anymap{
"log": builtinFunc{"log", func(args ...any) (any, ArErr) {
output := []any{}
for i := 0; i < len(args); i++ {
output = append(output, anyToArgon(args[i], false, true, 3, 0, false, 0))
}
fmt.Println(output...)
return nil, ArErr{}
}},
"logVal": builtinFunc{"logVal", func(args ...any) (any, ArErr) {
output := []any{}
for i := 0; i < len(args); i++ {
output = append(output, anyToArgon(args[i], true, true, 3, 0, false, 0))
}
fmt.Println(output...)
return nil, ArErr{}
}},
"print": builtinFunc{"print", func(args ...any) (any, ArErr) {
output := []any{}
for i := 0; i < len(args); i++ {
output = append(output, anyToArgon(args[i], false, false, 3, 0, false, 0))
}
fmt.Println(output...)
return nil, ArErr{}
}},
})
var ArTerm = Map(anymap{ var ArTerm = Map(anymap{
"log": builtinFunc{"log", func(args ...any) (any, ArErr) { "log": builtinFunc{"log", func(args ...any) (any, ArErr) {
output := []any{} output := []any{}
@@ -59,7 +32,40 @@ var ArTerm = Map(anymap{
fmt.Println(output...) fmt.Println(output...)
return nil, ArErr{} return nil, ArErr{}
}}, }},
"plain": plain, "plain": Map(anymap{
"log": builtinFunc{"log", func(args ...any) (any, ArErr) {
output := []any{}
for i := 0; i < len(args); i++ {
output = append(output, anyToArgon(args[i], false, true, 3, 0, false, 0))
}
fmt.Println(output...)
return nil, ArErr{}
}},
"logVal": builtinFunc{"logVal", func(args ...any) (any, ArErr) {
output := []any{}
for i := 0; i < len(args); i++ {
output = append(output, anyToArgon(args[i], true, true, 3, 0, false, 0))
}
fmt.Println(output...)
return nil, ArErr{}
}},
"print": builtinFunc{"print", func(args ...any) (any, ArErr) {
output := []any{}
for i := 0; i < len(args); i++ {
output = append(output, anyToArgon(args[i], false, false, 3, 0, false, 0))
}
fmt.Println(output...)
return nil, ArErr{}
}},
"oneLine": builtinFunc{"oneLine", func(args ...any) (any, ArErr) {
output := []any{}
for i := 0; i < len(args); i++ {
output = append(output, anyToArgon(args[i], false, false, 3, 0, false, 0))
}
fmt.Print(output...)
return nil, ArErr{}
}},
}),
"error": builtinFunc{"error", func(args ...any) (any, ArErr) { "error": builtinFunc{"error", func(args ...any) (any, ArErr) {
output := []any{"error: "} output := []any{"error: "}
for i := 0; i < len(args); i++ { for i := 0; i < len(args); i++ {
@@ -103,4 +109,18 @@ var ArTerm = Map(anymap{
fmt.Printf("\x1b[%dm%s\x1b[0m", 34, fmt.Sprint(anyToArgon(id, false, true, 3, 0, false, 0), ": ", timesince)+"\n") fmt.Printf("\x1b[%dm%s\x1b[0m", 34, fmt.Sprint(anyToArgon(id, false, true, 3, 0, false, 0), ": ", timesince)+"\n")
return nil, ArErr{} return nil, ArErr{}
}}, }},
"input": Map(
anymap{
"password": builtinFunc{"password", func(args ...any) (any, ArErr) {
resp, err := getPassword(args...)
if err != nil {
return nil, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
}
return ArString(resp), ArErr{}
}},
"__call__": builtinFunc{"input", func(args ...any) (any, ArErr) {
return input(args...), ArErr{}
}},
},
),
}) })

View File

@@ -1,7 +1,7 @@
package main package main
func typeof(val any) string { func typeof(val any) string {
switch val.(type) { switch x := val.(type) {
case number: case number:
return "number" return "number"
case nil: case nil:
@@ -10,14 +10,14 @@ func typeof(val any) string {
return "boolean" return "boolean"
case string: case string:
return "string" return "string"
case anymap: case []any:
return "array" return "array"
case Callable: case Callable:
return "function" return "function"
case builtinFunc: case builtinFunc:
return "function" return "function"
case ArObject: case ArObject:
return "map" return x.TYPE
case accessVariable: case accessVariable:
return "variable" return "variable"
} }