Files
argon-v3/src/array.go

693 lines
16 KiB
Go

package main
import (
"fmt"
"strings"
)
var arrayCompile = makeRegex(`( *)\[(.|\n)*\]( *)`)
type CreateArray struct {
value []any
line int
code string
path string
}
func isArray(code UNPARSEcode) bool {
return arrayCompile.MatchString(code.code)
}
func ArArray(arr []any) ArObject {
val := ArObject{
anymap{
"__name__": "array",
"__value__": arr,
},
}
val.obj["__setindex__"] = builtinFunc{
"__setindex__",
func(a ...any) (any, ArErr) {
if len(a) != 2 {
return nil, ArErr{
TYPE: "Type Error",
message: "expected 2 arguments, got " + fmt.Sprint(len(a)),
EXISTS: true,
}
}
if typeof(a[0]) != "number" {
return nil, ArErr{
TYPE: "Type Error",
message: "dex must be a number",
EXISTS: true,
}
}
if !a[0].(number).IsInt() {
return nil, ArErr{
TYPE: "Type Error",
message: "index must be an integer",
EXISTS: true,
}
}
num := int(a[0].(number).Num().Int64())
if num < 0 || num >= len(arr) {
return nil, ArErr{
TYPE: "Index Error",
message: "index out of range",
EXISTS: true,
}
}
arr[num] = a[1]
return nil, ArErr{}
},
}
val.obj["__Multiply__"] = builtinFunc{
"__Multiply__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"Type Error", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
if typeof(a[0]) != "number" {
return nil, ArErr{"Type Error", "cannot multiply array by " + typeof(a[0]), 0, "", "", true}
}
n := a[0].(number)
if !n.IsInt() {
return nil, ArErr{"Value Error", "cannot multiply array by float", 0, "", "", true}
}
if n.Sign() < 0 {
return nil, ArErr{"Value Error", "cannot multiply array by negative number", 0, "", "", true}
}
size := int(n.Num().Int64())
retval := make([]any, 0, len(arr)*size)
for i := 0; i < size; i++ {
retval = append(retval, arr...)
}
return ArArray(retval), ArErr{}
}}
val.obj["__getindex__"] = builtinFunc{
"__getindex__",
func(a ...any) (any, ArErr) {
// a[0] is start
// a[1] is end
// a[2] is step
if len(a) > 3 || len(a) == 0 {
return nil, ArErr{"Type Error", "expected 1 to 3 arguments, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
{
if len(a) == 1 {
if typeof(a[0]) == "string" {
var name = ArValidToAny(a[0]).(string)
if name == "length" {
return newNumber().SetInt64(int64(len(arr))), ArErr{}
}
}
}
}
var (
start int = 0
end any = nil
step int = 1
)
{
if a[0] == nil {
start = 0
} else if typeof(a[0]) != "number" || !a[0].(number).IsInt() {
return "", ArErr{
TYPE: "Type Error",
message: "slice index must be an integer",
EXISTS: true,
}
} else {
start = int(a[0].(number).Num().Int64())
}
}
if len(a) > 1 {
if a[1] == nil {
end = len(arr)
} else if typeof(a[1]) != "number" || !a[1].(number).IsInt() {
return "", ArErr{
TYPE: "Type Error",
message: "slice index must be an integer",
EXISTS: true,
}
} else {
end = int(a[1].(number).Num().Int64())
}
}
if len(a) > 2 {
if a[2] == nil {
step = 1
} else if typeof(a[2]) != "number" || !a[2].(number).IsInt() {
return "", ArErr{
TYPE: "Type Error",
message: "slice index must be an integer",
EXISTS: true,
}
} else {
step = int(a[2].(number).Num().Int64())
}
}
var ogStart = start
if start < 0 {
start = len(arr) + start
}
if _, ok := end.(int); ok && end.(int) < 0 {
end = len(arr) + end.(int)
}
if end != nil && end.(int) > len(arr) {
end = len(arr)
}
if start >= len(arr) || start < 0 {
return "", ArErr{
TYPE: "Index Error",
message: "index out of range, trying to access index " + fmt.Sprint(ogStart) + " in array of length " + fmt.Sprint(len(arr)),
EXISTS: true,
}
}
if end == nil {
return arr[start], ArErr{}
} else if step == 1 {
return arr[start:end.(int)], ArErr{}
} else {
output := []any{}
if step > 0 {
for i := start; i < end.(int); i += step {
output = append(output, arr[i])
}
} else {
for i := end.(int) - 1; i >= start; i += step {
output = append(output, arr[i])
}
}
return output, ArErr{}
}
}}
val.obj["remove"] = builtinFunc{
"remove",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument",
EXISTS: true,
}
}
if typeof(args[0]) != "number" {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be a number",
EXISTS: true,
}
}
if !args[0].(number).IsInt() {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be an integer",
EXISTS: true,
}
}
num := int(args[0].(number).Num().Int64())
if num < 0 || num >= len(arr) {
return nil, ArErr{
TYPE: "Index Error",
message: "index out of range",
EXISTS: true,
}
}
arr = append(arr[:num], arr[num+1:]...)
val.obj["__value__"] = arr
return nil, ArErr{}
}}
val.obj["append"] = builtinFunc{
"append",
func(args ...any) (any, ArErr) {
if len(args) == 0 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument",
EXISTS: true,
}
}
arr = append(arr, args...)
val.obj["__value__"] = arr
return nil, ArErr{}
},
}
val.obj["insert"] = builtinFunc{
"insert",
func(args ...any) (any, ArErr) {
if len(args) < 2 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument",
EXISTS: true,
}
}
if typeof(args[0]) != "number" {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be a number",
EXISTS: true,
}
}
if !args[0].(number).IsInt() {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be an integer",
EXISTS: true,
}
}
num := int(args[0].(number).Num().Int64())
if num < 0 || num > len(arr) {
return nil, ArErr{
TYPE: "Index Error",
message: "index out of range",
EXISTS: true,
}
}
arr = append(arr[:num], append(args[1:], arr[num:]...)...)
val.obj["__value__"] = arr
return nil, ArErr{}
},
}
val.obj["pop"] = builtinFunc{
"pop",
func(args ...any) (any, ArErr) {
if len(args) > 1 {
return nil, ArErr{
TYPE: "Type Error",
message: "too many arguments",
EXISTS: true,
}
}
if len(args) == 1 {
if typeof(args[0]) != "number" {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be a number",
EXISTS: true,
}
}
if !args[0].(number).IsInt() {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be an integer",
EXISTS: true,
}
}
num := int(args[0].(number).Num().Int64())
if num < 0 || num >= len(arr) {
return nil, ArErr{
TYPE: "Index Error",
message: "index out of range",
EXISTS: true,
}
}
v := arr[num]
arr = append(arr[:num], arr[num+1:]...)
val.obj["__value__"] = arr
return v, ArErr{}
}
v := arr[len(arr)-1]
arr = arr[:len(arr)-1]
val.obj["__value__"] = arr
return v, ArErr{}
},
}
val.obj["clear"] = builtinFunc{
"clear",
func(args ...any) (any, ArErr) {
if len(args) != 0 {
return nil, ArErr{
TYPE: "Type Error",
message: "too many arguments",
EXISTS: true,
}
}
arr = []any{}
val.obj["__value__"] = arr
return nil, ArErr{}
},
}
val.obj["extend"] = builtinFunc{
"extend",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument",
EXISTS: true,
}
}
if typeof(args[0]) != "array" {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be an array",
EXISTS: true,
}
}
arr = append(arr, args[0].(ArObject).obj["__value__"].([]any)...)
val.obj["__value__"] = arr
return nil, ArErr{}
},
}
val.obj["sort"] = builtinFunc{
"sort",
func(args ...any) (any, ArErr) {
if len(args) > 2 {
return nil, ArErr{
TYPE: "Type Error",
message: "too many arguments",
EXISTS: true,
}
}
reverse := false
if len(args) >= 1 {
if typeof(args[0]) != "boolean" {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be a boolean",
EXISTS: true,
}
}
reverse = args[0].(bool)
}
if len(args) == 2 {
if typeof(args[1]) != "function" {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be a function",
EXISTS: true,
}
}
output, err := quickSort(arr, func(a any) (any, ArErr) {
return runCall(call{
args[1],
[]any{a}, "", 0, "",
}, stack{}, 0)
})
if err.EXISTS {
return nil, err
}
if reverse {
for i, j := 0, len(output)-1; i < j; i, j = i+1, j-1 {
output[i], output[j] = output[j], output[i]
}
}
arr = output
val.obj["__value__"] = arr
return nil, ArErr{}
}
output, err := quickSort(arr, func(a any) (any, ArErr) {
return a, ArErr{}
})
if err.EXISTS {
return nil, err
}
if reverse {
for i, j := 0, len(output)-1; i < j; i, j = i+1, j-1 {
output[i], output[j] = output[j], output[i]
}
}
arr = output
val.obj["__value__"] = arr
return nil, ArErr{}
},
}
val.obj["map"] = builtinFunc{
"map",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument",
EXISTS: true,
}
}
if typeof(args[0]) != "function" {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be a function",
EXISTS: true,
}
}
newarr := []any{}
for _, v := range arr {
vv, err := runCall(call{
args[0],
[]any{v}, "", 0, "",
}, stack{}, 0)
if err.EXISTS {
return nil, err
}
newarr = append(newarr, vv)
}
return ArArray(newarr), ArErr{}
},
}
val.obj["filter"] = builtinFunc{
"filter",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument",
EXISTS: true,
}
}
if typeof(args[0]) != "function" {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be a function",
EXISTS: true,
}
}
newarr := []any{}
for _, v := range arr {
vv, err := runCall(call{
args[0],
[]any{v}, "", 0, "",
}, stack{}, 0)
if err.EXISTS {
return nil, err
}
if anyToBool(vv) {
newarr = append(newarr, v)
}
}
return ArArray(newarr), ArErr{}
},
}
val.obj["reduce"] = builtinFunc{
"reduce",
func(args ...any) (any, ArErr) {
if len(args) != 2 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument, expected 2 got " + fmt.Sprint(len(args)),
EXISTS: true,
}
}
if typeof(args[0]) != "function" {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be a function",
EXISTS: true,
}
}
if len(arr) == 0 {
return nil, ArErr{
TYPE: "Value Error",
message: "array is empty",
EXISTS: true,
}
}
v := args[1]
for _, vv := range arr {
var err ArErr
v, err = runCall(call{
args[0],
[]any{v, vv}, "", 0, "",
}, stack{}, 0)
if err.EXISTS {
return nil, err
}
}
return v, ArErr{}
},
}
val.obj["join"] = builtinFunc{
"join",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument",
EXISTS: true,
}
}
if typeof(args[0]) != "string" {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be a string",
EXISTS: true,
}
}
output := []string{}
for _, v := range arr {
if typeof(v) != "string" {
return nil, ArErr{
TYPE: "Type Error",
message: "array must be an array of strings",
EXISTS: true,
}
}
output = append(output, v.(ArObject).obj["__value__"].(string))
}
return ArString(strings.Join(output, args[0].(ArObject).obj["__value__"].(string))), ArErr{}
},
}
val.obj["concat"] = builtinFunc{
"concat",
func(args ...any) (any, ArErr) {
if len(args) < 1 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument(s)",
EXISTS: true,
}
}
if typeof(args[0]) != "array" {
return nil, ArErr{
TYPE: "Type Error",
message: "argument must be an array",
EXISTS: true,
}
}
newarr := append(arr, args[0].(ArObject).obj["__value__"].([]any)...)
return ArArray(newarr), ArErr{}
},
}
val.obj["__Equal__"] = builtinFunc{
"__Equal__",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument",
EXISTS: true,
}
}
if typeof(args[0]) != "array" {
return false, ArErr{}
}
if len(arr) != len(args[0].(ArObject).obj["__value__"].([]any)) {
return false, ArErr{}
}
for i, v := range arr {
res, err := runOperation(operationType{
operation: 8,
values: []any{v, args[0].(ArObject).obj["__value__"].([]any)[i]},
}, stack{}, 0)
if err.EXISTS {
return nil, err
}
if anyToBool(res) {
return false, ArErr{}
}
}
return true, ArErr{}
}}
val.obj["__Contains__"] = builtinFunc{
"__Contains__",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument",
EXISTS: true,
}
}
for _, v := range arr {
res, err := runOperation(operationType{
operation: 9,
values: []any{v, args[0]},
}, stack{}, 0)
if err.EXISTS {
return nil, err
}
if anyToBool(res) {
return true, ArErr{}
}
}
return false, ArErr{}
},
}
val.obj["__NotContains__"] = builtinFunc{
"__NotContains__",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "Type Error",
message: "missing argument",
EXISTS: true,
}
}
for _, v := range arr {
res, err := runOperation(operationType{
operation: 9,
values: []any{v, args[0]},
}, stack{}, 0)
if err.EXISTS {
return nil, err
}
if anyToBool(res) {
return false, ArErr{}
}
}
return true, ArErr{}
},
}
val.obj["copy"] = builtinFunc{
"copy",
func(args ...any) (any, ArErr) {
arrCopy := make([]any, len(arr))
copy(arrCopy, arr)
return ArArray(arrCopy), ArErr{}
},
}
val.obj["__Boolean__"] = builtinFunc{
"__Boolean__",
func(args ...any) (any, ArErr) {
return len(
arr,
) > 0, ArErr{}
},
}
return val
}
func parseArray(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, ArErr, int) {
trimmed := strings.TrimSpace(code.code)
trimmed = trimmed[1 : len(trimmed)-1]
arguments, worked, err := getValuesFromLetter(trimmed, ",", index, codelines, true)
return CreateArray{
value: arguments,
line: code.line,
code: code.realcode,
path: code.path,
}, worked, err, 1
}
func runArray(a CreateArray, stack stack, stacklevel int) (ArObject, ArErr) {
var array []any
for _, val := range a.value {
val, err := runVal(val, stack, stacklevel+1)
if err.EXISTS {
return ArObject{}, err
}
array = append(array, val)
}
return ArArray(array), ArErr{}
}