abs and modify operations so they are opp

This commit is contained in:
2023-03-26 21:42:44 +01:00
parent e06d28ca02
commit aea3b73e71
11 changed files with 656 additions and 185 deletions

2
go.mod
View File

@@ -1,4 +1,4 @@
module wbell.dev/m/v2
module argon.wbell.dev
go 1.19

77
src/abs.go Normal file
View File

@@ -0,0 +1,77 @@
package main
import (
"fmt"
"strings"
)
var AbsCompiled = makeRegex(`( *)\|(.|\n)+\|( *)`)
type ABS struct {
body any
code string
line int
path string
}
func isAbs(code UNPARSEcode) bool {
return AbsCompiled.MatchString(code.code)
}
func parseAbs(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, ArErr, int) {
trimmed := strings.TrimSpace(code.code)
trimmed = trimmed[1 : len(trimmed)-1]
val, worked, err, i := translateVal(UNPARSEcode{
trimmed,
code.realcode,
code.line,
code.path,
}, index, codelines, 0)
if !worked {
return nil, false, err, 0
}
return ABS{
val,
code.realcode,
code.line,
code.path,
}, true, ArErr{}, i
}
func runAbs(x ABS, stack stack, stacklevel int) (any, ArErr) {
resp, err := runVal(x.body, stack, stacklevel+1)
if err.EXISTS {
return nil, err
}
if typeof(resp) != "number" {
return nil, ArErr{TYPE: "Runtime Error",
message: fmt.Sprintf("abs expected number, got %s", typeof(resp)),
EXISTS: true,
}
}
return abs(resp.(number)), ArErr{}
}
func abs(x number) number {
if x.Sign() < 0 {
return x.Neg(x)
}
return x
}
var ArAbs = builtinFunc{"abs", func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{TYPE: "Runtime Error",
message: fmt.Sprintf("abs expected 1 argument, got %d", len(args)),
EXISTS: true,
}
}
if typeof(args[0]) != "number" {
return nil, ArErr{TYPE: "Runtime Error",
message: fmt.Sprintf("abs expected number, got %s", typeof(args[0])),
EXISTS: true,
}
}
return abs(args[0].(number)), ArErr{}
}}

View File

@@ -533,6 +533,36 @@ func ArArray(arr []any) ArObject {
return ArArray(newarr), ArErr{}
},
}
val.obj["__Equal__"] = builtinFunc{
"__LessThanEqual__",
func(args ...any) (any, ArErr) {
if len(args) != 1 {
return nil, ArErr{
TYPE: "TypeError",
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{}
}}
return val
}

View File

@@ -10,6 +10,9 @@ type builtinFunc struct {
}
func ArgonString(args ...any) (any, ArErr) {
if len(args) == 0 {
return ArString(""), ArErr{}
}
return ArString(anyToArgon(args[0], true, false, 3, 0, false, 0)), ArErr{}
}

View File

@@ -149,6 +149,7 @@ func makeGlobal(allowDocument bool) ArObject {
vars.obj["arccot"] = ArArccot
vars.obj["todeg"] = ArToDeg
vars.obj["torad"] = ArToRad
vars.obj["abs"] = ArAbs
vars.obj["dir"] = builtinFunc{"dir", func(a ...any) (any, ArErr) {
fmt.Println(a)
if len(a) == 0 {

View File

@@ -7,6 +7,13 @@ import (
var mapCompiled = makeRegex(`( *)\{(((( *).+( *):( *).+( *))|(` + spacelessVariable + `))(( *)\,(( *).+( *):( *).+( *))|(` + spacelessVariable + `)))*\}( *)`)
type createMap struct {
body anymap
code string
line int
path string
}
func isMap(code UNPARSEcode) bool {
return mapCompiled.MatchString(code.code)
}

View File

@@ -4,7 +4,6 @@ import (
"fmt"
"math"
"reflect"
"strings"
)
var operations = [][]string{
@@ -121,7 +120,6 @@ func compareValues(o operationType, stack stack, stacklevel int) (bool, ArErr) {
stack,
stacklevel+1,
)
resp = ArValidToAny(resp)
if err.EXISTS {
return false, err
}
@@ -139,6 +137,21 @@ func compareValues(o operationType, stack stack, stacklevel int) (bool, ArErr) {
case 4:
if isAnyNumber(resp) && isAnyNumber(resp2) {
return resp.(number).Cmp(resp2.(number)) <= 0, ArErr{}
} else if x, ok := resp.(ArObject); ok {
if y, ok := x.obj["__LessThanEqual__"]; ok {
val, err := runCall(
call{
y,
[]any{resp2},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return false, err
}
return anyToBool(val), ArErr{}
}
}
return false, ArErr{
"Runtime Error",
@@ -151,6 +164,21 @@ func compareValues(o operationType, stack stack, stacklevel int) (bool, ArErr) {
case 5:
if isAnyNumber(resp) && isAnyNumber(resp2) {
return resp.(number).Cmp(resp2.(number)) >= 0, ArErr{}
} else if x, ok := resp.(ArObject); ok {
if y, ok := x.obj["__GreaterThanEqual__"]; ok {
val, err := runCall(
call{
y,
[]any{resp2},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return false, err
}
return anyToBool(val), ArErr{}
}
}
return false, ArErr{
"Runtime Error",
@@ -163,6 +191,21 @@ func compareValues(o operationType, stack stack, stacklevel int) (bool, ArErr) {
case 6:
if isAnyNumber(resp) && isAnyNumber(resp2) {
return resp.(number).Cmp(resp2.(number)) < 0, ArErr{}
} else if x, ok := resp.(ArObject); ok {
if y, ok := x.obj["__LessThan__"]; ok {
val, err := runCall(
call{
y,
[]any{resp2},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return false, err
}
return anyToBool(val), ArErr{}
}
}
return false, ArErr{
"Runtime Error",
@@ -175,6 +218,21 @@ func compareValues(o operationType, stack stack, stacklevel int) (bool, ArErr) {
case 7:
if isAnyNumber(resp) && isAnyNumber(resp2) {
return resp.(number).Cmp(resp2.(number)) > 0, ArErr{}
} else if x, ok := resp.(ArObject); ok {
if y, ok := x.obj["__GreaterThan__"]; ok {
val, err := runCall(
call{
y,
[]any{resp2},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return false, err
}
return anyToBool(val), ArErr{}
}
}
return false, ArErr{
"Runtime Error",
@@ -185,9 +243,9 @@ func compareValues(o operationType, stack stack, stacklevel int) (bool, ArErr) {
true,
}
case 8:
return !equals(resp, resp2), ArErr{}
return notequals(resp, resp2, o, stack, stacklevel)
case 9:
return equals(resp, resp2), ArErr{}
return equals(resp, resp2, o, stack, stacklevel)
default:
return false, ArErr{
"Runtime Error",
@@ -200,76 +258,75 @@ func compareValues(o operationType, stack stack, stacklevel int) (bool, ArErr) {
}
}
func calcNegative(o operationType, stack stack, stacklevel int) (number, ArErr) {
func calcNegative(o operationType, stack stack, stacklevel int) (any, ArErr) {
resp, err := runVal(
o.values[0],
stack,
stacklevel+1,
)
resp = ArValidToAny(resp)
if err.EXISTS {
return nil, err
}
if !isAnyNumber(resp) {
return nil, ArErr{
"Runtime Error",
"Cannot subtract from type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
}
output := resp
if isAnyNumber(resp) {
output = newNumber().Set(resp.(number))
}
output := newNumber().Set(resp.(number))
for i := 1; i < len(o.values); i++ {
resp, err := runVal(
o.values[i],
stack,
stacklevel+1,
)
resp = ArValidToAny(resp)
if err.EXISTS {
return nil, err
}
if typeof(resp) == "number" {
output = output.Sub(output, resp.(number))
} else {
return nil, ArErr{
"Runtime Error",
"Cannot subtract type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
if typeof(output) == "number" && typeof(resp) == "number" {
output = output.(number).Sub(output.(number), resp.(number))
continue
} else if x, ok := output.(ArObject); ok {
if y, ok := x.obj["__Subtract__"]; ok {
val, err := runCall(
call{
y,
[]any{resp},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return nil, err
}
output = val
continue
}
}
return nil, ArErr{
"Runtime Error",
"Cannot subtract type '" + typeof(resp) + "' from type '" + typeof(output) + "'",
o.line,
o.path,
o.code,
true,
}
}
return output, ArErr{}
}
func calcDivide(o operationType, stack stack, stacklevel int) (number, ArErr) {
func calcDivide(o operationType, stack stack, stacklevel int) (any, ArErr) {
resp, err := runVal(
o.values[0],
stack,
stacklevel+1,
)
resp = ArValidToAny(resp)
if err.EXISTS {
return nil, err
}
if !isAnyNumber(resp) {
return nil, ArErr{
"Runtime Error",
"Cannot divide from type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
}
output := resp
if isAnyNumber(resp) {
output = newNumber().Set(resp.(number))
}
output := newNumber().Set(resp.(number))
for i := 1; i < len(o.values); i++ {
resp, err := runVal(
o.values[i],
@@ -280,18 +337,34 @@ func calcDivide(o operationType, stack stack, stacklevel int) (number, ArErr) {
if err.EXISTS {
return nil, err
}
if typeof(resp) == "number" {
output = output.Quo(output, resp.(number))
} else {
return nil, ArErr{
"Runtime Error",
"Cannot divide type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
if typeof(resp) == "number" && typeof(output) == "number" {
output = output.(number).Quo(output.(number), resp.(number))
continue
} else if x, ok := output.(ArObject); ok {
if y, ok := x.obj["__Divide__"]; ok {
val, err := runCall(
call{
y,
[]any{resp},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return nil, err
}
output = val
continue
}
}
return nil, ArErr{
"Runtime Error",
"Cannot divide type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
}
}
return output, ArErr{}
}
@@ -303,14 +376,11 @@ func calcAdd(o operationType, stack stack, stacklevel int) (any, ArErr) {
stack,
stacklevel+1,
)
resp = ArValidToAny(resp)
if err.EXISTS {
return nil, err
}
var output any = resp
if typeof(output) != "number" {
output = anyToArgon(resp, false, true, 3, 0, false, 0)
} else {
if typeof(output) == "number" {
output = newNumber().Set(output.(number))
}
for i := 1; i < len(o.values); i++ {
@@ -319,21 +389,39 @@ func calcAdd(o operationType, stack stack, stacklevel int) (any, ArErr) {
stack,
stacklevel+1,
)
resp = ArValidToAny(resp)
if err.EXISTS {
return nil, err
}
if typeof(output) == "number" && typeof(resp) == "string" {
output = anyToArgon(output, false, true, 3, 0, false, 0)
}
if typeof(output) == "number" {
if typeof(output) == "number" && typeof(resp) == "number" {
output = output.(number).Add(output.(number), resp.(number))
} else {
output = output.(string) + anyToArgon(resp, false, true, 3, 0, false, 0)
continue
} else if x, ok := output.(ArObject); ok {
if y, ok := x.obj["__Add__"]; ok {
val, err := runCall(
call{
y,
[]any{resp},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return nil, err
}
output = val
continue
}
}
return nil, ArErr{
"Runtime Error",
"Cannot add type '" + typeof(resp) + "' to type '" + typeof(output) + "'",
o.line,
o.path,
o.code,
true,
}
}
return AnyToArValid(output), ArErr{}
return (output), ArErr{}
}
func calcMul(o operationType, stack stack, stacklevel int) (any, ArErr) {
@@ -343,15 +431,12 @@ func calcMul(o operationType, stack stack, stacklevel int) (any, ArErr) {
stack,
stacklevel+1,
)
resp = ArValidToAny(resp)
if err.EXISTS {
return nil, err
}
var output any = resp
if typeof(output) != "number" {
output = anyToArgon(resp, false, true, 3, 0, false, 0)
} else {
output = newNumber().Set(output.(number))
if isAnyNumber(resp) {
output = newNumber().Set(resp.(number))
}
for i := 1; i < len(o.values); i++ {
resp, err := runVal(
@@ -359,28 +444,38 @@ func calcMul(o operationType, stack stack, stacklevel int) (any, ArErr) {
stack,
stacklevel+1,
)
resp = ArValidToAny(resp)
if err.EXISTS {
return nil, err
}
if typeof(output) == "number" && typeof(resp) == "string" {
output = anyToArgon(output, false, true, 3, 0, false, 0)
}
if typeof(output) == "number" {
if typeof(output) == "number" && typeof(resp) == "number" {
output = output.(number).Mul(output.(number), resp.(number))
} else if typeof(resp) == "number" {
n, _ := resp.(number).Float64()
output = strings.Repeat(output.(string), int(n))
} else {
return nil, ArErr{
"Runtime Error",
"Cannot multiply type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
continue
} else if x, ok := output.(ArObject); ok {
if y, ok := x.obj["__Multiply__"]; ok {
val, err := runCall(
call{
y,
[]any{resp},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return nil, err
}
output = val
continue
}
}
return nil, ArErr{
"Runtime Error",
"Cannot multiply type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
}
}
return output, ArErr{}
}
@@ -425,7 +520,7 @@ func calcOr(o operationType, stack stack, stacklevel int) (any, ArErr) {
return output, ArErr{}
}
func stringInSlice(a any, list []any) bool {
func InSlice(a any, list []any) bool {
for _, b := range list {
if b == a {
return true
@@ -433,8 +528,7 @@ func stringInSlice(a any, list []any) bool {
}
return false
}
func calcIn(o operationType, stack stack, stacklevel int) (bool, ArErr) {
func calcNotIn(o operationType, stack stack, stacklevel int) (any, ArErr) {
if len(o.values) != 2 {
return false, ArErr{
"Runtime Error",
@@ -460,42 +554,125 @@ func calcIn(o operationType, stack stack, stacklevel int) (bool, ArErr) {
stack,
stacklevel+1,
)
resp2 = ArValidToAny(resp2)
if err.EXISTS {
return false, err
}
if x, ok := resp.(ArObject); ok {
if y, ok := x.obj["__NotContains__"]; ok {
return runCall(
call{
y,
[]any{resp2},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
}
}
return false, ArErr{
"Runtime Error",
"Cannot check if type '" + typeof(resp) + "' is in type '" + typeof(resp2) + "'",
o.line,
o.path,
o.code,
true,
}
}
switch x := resp2.(type) {
case string:
check := anyToArgon(resp, false, true, 3, 0, false, 0)
return strings.Contains(x, check), ArErr{}
case []any:
return stringInSlice(resp, x), ArErr{}
case map[any]any:
_, ok := x[resp]
return ok, ArErr{}
default:
func calcIn(o operationType, stack stack, stacklevel int) (any, ArErr) {
if len(o.values) != 2 {
return false, ArErr{
"Runtime Error",
"Cannot check if type '" + typeof(resp) + "' is in type '" + typeof(resp2) + "'",
"Invalid number of arguments for 'not in'",
o.line,
o.path,
o.code,
true,
}
}
}
func equals(a any, b any) bool {
if typeof(a) == "number" && typeof(b) == "number" {
return a.(number).Cmp(b.(number)) == 0
} else if typeof(a) == "string" || typeof(b) == "string" {
return anyToArgon(a, false, false, 3, 0, false, 0) == anyToArgon(b, false, false, 3, 0, false, 0)
resp, err := runVal(
o.values[0],
stack,
stacklevel+1,
)
if err.EXISTS {
return false, err
}
return reflect.DeepEqual(a, b)
resp2, err := runVal(
o.values[1],
stack,
stacklevel+1,
)
if err.EXISTS {
return false, err
}
if x, ok := resp2.(ArObject); ok {
if y, ok := x.obj["__Contains__"]; ok {
return runCall(
call{
y,
[]any{resp},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
}
}
return false, ArErr{
"Runtime Error",
"Cannot check if type '" + typeof(resp) + "' is in type '" + typeof(resp2) + "'",
o.line,
o.path,
o.code,
true,
}
}
func notequals(a any, b any, o operationType, stack stack, stacklevel int) (bool, ArErr) {
if typeof(a) == "number" && typeof(b) == "number" {
return a.(number).Cmp(b.(number)) != 0, ArErr{}
} else if x, ok := a.(ArObject); ok {
if y, ok := x.obj["__NotEqual__"]; ok {
val, err := runCall(
call{
y,
[]any{b},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return false, err
}
return !anyToBool(val), ArErr{}
}
}
return !reflect.DeepEqual(a, b), ArErr{}
}
func calcMod(o operationType, stack stack, stacklevel int) (number, ArErr) {
func equals(a any, b any, o operationType, stack stack, stacklevel int) (bool, ArErr) {
if typeof(a) == "number" && typeof(b) == "number" {
return a.(number).Cmp(b.(number)) == 0, ArErr{}
} else if x, ok := a.(ArObject); ok {
if y, ok := x.obj["__Equal__"]; ok {
val, err := runCall(
call{
y,
[]any{b},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return false, err
}
return anyToBool(val), ArErr{}
}
}
return reflect.DeepEqual(a, b), ArErr{}
}
func calcMod(o operationType, stack stack, stacklevel int) (any, ArErr) {
resp, err := runVal(
o.values[0],
stack,
@@ -505,17 +682,10 @@ func calcMod(o operationType, stack stack, stacklevel int) (number, ArErr) {
if err.EXISTS {
return nil, err
}
if !isAnyNumber(resp) {
return nil, ArErr{
"Runtime Error",
"Cannot calculate modulus from type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
}
output := resp
if isAnyNumber(resp) {
output = newNumber().Set(resp.(number))
}
output := newNumber().Set(resp.(number))
for i := 1; i < len(o.values); i++ {
resp, err := runVal(
o.values[i],
@@ -526,29 +696,91 @@ func calcMod(o operationType, stack stack, stacklevel int) (number, ArErr) {
if err.EXISTS {
return nil, err
}
if typeof(resp) == "number" {
n1, _ := output.Float64()
n2, _ := resp.(number).Float64()
output = newNumber().SetFloat64(math.Mod(n1, n2))
} else {
return nil, ArErr{
"Runtime Error",
"Cannot calculate modulus of type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
if typeof(resp) == "number" && typeof(output) == "number" {
output = floor(newNumber().Quo(resp.(number), output.(number)))
continue
} else if x, ok := output.(ArObject); ok {
if y, ok := x.obj["__Modulo__"]; ok {
val, err := runCall(
call{
y,
[]any{resp},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return nil, err
}
output = val
continue
}
}
return nil, ArErr{
"Runtime Error",
"Cannot calculate modulus of type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
}
}
return output, ArErr{}
}
func calcIntDiv(o operationType, stack stack, stacklevel int) (number, ArErr) {
resp, err := calcDivide(o, stack, stacklevel+1)
x, _ := resp.Float64()
resp = newNumber().SetFloat64(math.Trunc(x))
return resp, err
func calcIntDiv(o operationType, stack stack, stacklevel int) (any, ArErr) {
resp, err := runVal(
o.values[0],
stack,
stacklevel+1,
)
if err.EXISTS {
return nil, err
}
output := resp
if isAnyNumber(resp) {
output = newNumber().Set(resp.(number))
}
for i := 1; i < len(o.values); i++ {
resp, err := runVal(
o.values[i],
stack,
stacklevel+1,
)
resp = ArValidToAny(resp)
if err.EXISTS {
return nil, err
}
if typeof(resp) == "number" && typeof(output) == "number" {
output = output.(number).Quo(output.(number), resp.(number))
continue
} else if x, ok := output.(ArObject); ok {
if y, ok := x.obj["__IntDivide__"]; ok {
val, err := runCall(
call{
y,
[]any{resp},
o.code,
o.line,
o.path,
}, stack, stacklevel+1)
if err.EXISTS {
return nil, err
}
output = val
continue
}
}
return nil, ArErr{
"Runtime Error",
"Cannot divide type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
}
}
return output, ArErr{}
}
func calcPower(o operationType, stack stack, stacklevel int) (number, ArErr) {
@@ -610,22 +842,10 @@ func runOperation(o operationType, stack stack, stacklevel int) (any, ArErr) {
case 1:
return calcOr(o, stack, stacklevel+1)
case 2:
resp, err := calcIn(o, stack, stacklevel+1)
resp = !resp
return resp, err
return calcNotIn(o, stack, stacklevel+1)
case 3:
return calcIn(o, stack, stacklevel+1)
case 4:
return compareValues(o, stack, stacklevel+1)
case 5:
return compareValues(o, stack, stacklevel+1)
case 6:
return compareValues(o, stack, stacklevel+1)
case 7:
return compareValues(o, stack, stacklevel+1)
case 8:
return compareValues(o, stack, stacklevel+1)
case 9:
case 4, 5, 6, 7, 8, 9:
return compareValues(o, stack, stacklevel+1)
case 10:
return calcAdd(o, stack, stacklevel+1)

View File

@@ -14,8 +14,6 @@ func runVal(line any, stack stack, stacklevel int) (any, ArErr) {
stackoverflow = stacklevel >= 10000
)
switch x := line.(type) {
case number:
return x, ArErr{}
case string:
return ArString(x), ArErr{}
case call:
@@ -191,11 +189,15 @@ func runVal(line any, stack stack, stacklevel int) (any, ArErr) {
break
}
return runImport(x, stack, stacklevel+1)
case bool:
return x, ArErr{}
case nil:
return x, ArErr{}
case ArObject:
case ABS:
if stackoverflow {
linenum = x.line
path = x.path
code = x.code
break
}
return runAbs(x, stack, stacklevel+1)
case bool, ArObject, number, nil:
return x, ArErr{}
}
if stackoverflow {

View File

@@ -32,7 +32,7 @@ func quickSort(list []interface{}, getKey func(interface{}) (interface{}, ArErr)
EXISTS: true,
}
}
if comp < 0 {
if comp {
left = append(left, v)
} else {
right = append(right, v)
@@ -52,35 +52,32 @@ func quickSort(list []interface{}, getKey func(interface{}) (interface{}, ArErr)
}
func getkeyCache(getKey func(interface{}) (interface{}, ArErr), index interface{}, cache keyCache) (interface{}, ArErr) {
if cacheval, ok := cache[index]; ok {
key := ArValidToAny(index)
if cacheval, ok := cache[key]; ok {
return cacheval, ArErr{}
}
val, err := getKey(index)
if err.EXISTS {
return nil, err
}
cache[index] = val
cache[key] = val
return val, ArErr{}
}
func compare(a, b interface{}) (int, error) {
switch x := a.(type) {
case string:
if _, ok := b.(string); !ok {
return 0, fmt.Errorf("cannot compare %T to %T", a, b)
func compare(a, b any) (bool, error) {
if isAnyNumber(a) && isAnyNumber(b) {
return a.(number).Cmp(b.(number)) < 0, nil
} else if x, ok := a.(ArObject); ok {
if y, ok := x.obj["__LessThan__"]; ok {
resp, err := runCall(
call{
callable: y,
args: []any{b},
}, stack{}, 0)
if !err.EXISTS {
return anyToBool(resp), nil
}
}
if a == b {
return 0, nil
}
if x < b.(string) {
return -1, nil
}
return 1, nil
case number:
if _, ok := b.(number); !ok {
return 0, fmt.Errorf("cannot compare %T to %T", a, b)
}
return x.Cmp(b.(number)), nil
}
return 0, fmt.Errorf("cannot compare %T to %T", a, b)
return false, fmt.Errorf("cannot compare %s to %s", typeof(a), typeof(b))
}

View File

@@ -30,8 +30,7 @@ func unquoted(
if err != nil {
return "", err
}
classoutput := (output)
return classoutput, nil
return output, nil
}
// returns translateString, success, error
@@ -256,8 +255,8 @@ func ArString(str string) ArObject {
}
splitby := a[0].(string)
output := []any{}
splitted := any(strings.Split(str, splitby))
for _, v := range splitted.([]string) {
splitted := (strings.Split(str, splitby))
for _, v := range splitted {
output = append(output, ArString(v))
}
return output, ArErr{}
@@ -412,5 +411,134 @@ func ArString(str string) ArObject {
}
return strings.TrimRight(str, cutset), ArErr{}
}}
obj.obj["__LessThanEqual__"] = builtinFunc{
"__LessThanOrEqual__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot get less than or equal to of type " + typeof(a[0]) + " from string", 0, "", "", true}
}
return str <= a[0].(string), ArErr{}
}}
obj.obj["__LessThan__"] = builtinFunc{
"__LessThan__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot get less than of type " + typeof(a[0]) + " from string", 0, "", "", true}
}
return str < a[0].(string), ArErr{}
}}
obj.obj["__GreaterThan__"] = builtinFunc{
"__GreaterThan__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot get greater than of type " + typeof(a[0]) + " from string", 0, "", "", true}
}
return str > a[0].(string), ArErr{}
}}
obj.obj["__GreaterThanEqual__"] = builtinFunc{
"__GreaterThanEqual__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot get greater than or equal to of type " + typeof(a[0]) + " from string", 0, "", "", true}
}
return str >= a[0].(string), ArErr{}
}}
obj.obj["__Equal__"] = builtinFunc{
"__Equal__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
return str == a[0], ArErr{}
}}
obj.obj["__NotEqual__"] = builtinFunc{
"__NotEqual__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
return str != a[0], ArErr{}
}}
obj.obj["__Add__"] = builtinFunc{
"__Add__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot add " + typeof(a[0]) + " to string", 0, "", "", true}
}
return strings.Join([]string{str, a[0].(string)}, ""), ArErr{}
}}
obj.obj["__Multiply__"] = builtinFunc{
"__Multiply__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
if typeof(a[0]) != "number" {
return nil, ArErr{"TypeError", "cannot multiply string by " + typeof(a[0]), 0, "", "", true}
}
n := a[0].(number)
if !n.IsInt() {
return nil, ArErr{"ValueError", "cannot multiply string by float", 0, "", "", true}
}
if n.Sign() < 0 {
return nil, ArErr{"ValueError", "cannot multiply string by negative number", 0, "", "", true}
}
return strings.Repeat(str, int(n.Num().Int64())), ArErr{}
}}
obj.obj["__Contains__"] = builtinFunc{
"__Contains__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot check if string contains " + typeof(a[0]), 0, "", "", true}
}
return strings.Contains(str, a[0].(string)), ArErr{}
}}
obj.obj["__Subtract__"] = builtinFunc{
"__Subtract__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot subtract " + typeof(a[0]) + " from string", 0, "", "", true}
}
return strings.Replace(str, a[0].(string), "", -1), ArErr{}
}}
obj.obj["__Divide__"] = builtinFunc{
"__Divide__",
func(a ...any) (any, ArErr) {
if len(a) != 1 {
return nil, ArErr{"TypeError", "expected 1 argument, got " + fmt.Sprint(len(a)), 0, "", "", true}
}
if typeof(a[0]) != "string" {
return nil, ArErr{"TypeError", "cannot divide string by " + typeof(a[0]), 0, "", "", true}
}
splitby := a[0].(string)
output := []any{}
splitted := (strings.Split(str, splitby))
for _, v := range splitted {
output = append(output, ArString(v))
}
return ArArray(output), ArErr{}
}}
return obj
}

View File

@@ -62,6 +62,12 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i
return resp, worked, err, i
}
}
if isAbs(code) {
resp, worked, err, i = parseAbs(code, index, codelines)
if worked {
return resp, worked, err, i
}
}
if isnot(code) {
return parseNot(code, index, codelines, isLine)
}
@@ -79,8 +85,6 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i
}
if isNumber(code) {
return parseNumber(code)
} else if isNegative(code) {
return parseNegative(code, index, codelines)
} else if isString(code) {
return parseString(code)
} else if issquareroot(code) {
@@ -105,7 +109,9 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i
return nil, worked, err, step
}
}
if isCall(code) {
if isNegative(code) {
return parseNegative(code, index, codelines)
} else if isCall(code) {
resp, worked, err, i = parseCall(code, index, codelines)
if worked {
return resp, worked, err, i