make for loops use int64 to hopefully speed up iterations

This commit is contained in:
2024-07-10 12:30:06 +01:00
parent 14a94274c4
commit b4a02be086
6 changed files with 884 additions and 461 deletions

View File

@@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"math/big"
"strings" "strings"
) )
@@ -126,7 +125,7 @@ func ArArray(arr []any) ArObject {
if typeof(a[0]) == "string" { if typeof(a[0]) == "string" {
var name = ArValidToAny(a[0]).(string) var name = ArValidToAny(a[0]).(string)
if name == "length" { if name == "length" {
return Number(compiledNumber{big.NewInt(int64(len(arr)))}), ArErr{} return Number(len(arr)), ArErr{}
} }
} }
} }

View File

@@ -1,7 +1,6 @@
package main package main
import ( import (
"fmt"
"strings" "strings"
) )
@@ -100,8 +99,31 @@ func runForLoop(loop forLoop, stack stack, stacklevel int) (any, ArErr) {
if typeof(stepval) != "number" { if typeof(stepval) != "number" {
return nil, ArErr{"Type Error", "for loop step value must be a number", loop.line, loop.path, loop.code, true} return nil, ArErr{"Type Error", "for loop step value must be a number", loop.line, loop.path, loop.code, true}
} }
i := from
step := stepval.(ArObject) step := stepval.(ArObject)
if isNumberInt64(from) && isNumberInt64(to) && isNumberInt64(step) {
i, _ := numberToInt64(from)
to_, _ := numberToInt64(to)
step_, _ := numberToInt64(step)
layer := anymap{}
stacks := append(stack, Map(layer))
for i <= to_ {
layer[loop.variable] = Number(i)
resp, err := runVal(loop.body, stacks, stacklevel+1)
if err.EXISTS {
return nil, err
}
switch x := resp.(type) {
case Return:
return x, ArErr{}
case Break:
return nil, ArErr{}
case Continue:
}
i += step_
}
return nil, ArErr{}
}
i := from
direction_obj, err := CompareObjects(step, _zero_Number) direction_obj, err := CompareObjects(step, _zero_Number)
if err.EXISTS { if err.EXISTS {
return nil, err return nil, err
@@ -118,11 +140,11 @@ func runForLoop(loop forLoop, stack stack, stacklevel int) (any, ArErr) {
if error != nil { if error != nil {
return nil, ArErr{"Type Error", error.Error(), loop.line, loop.path, loop.code, true} return nil, ArErr{"Type Error", error.Error(), loop.line, loop.path, loop.code, true}
} }
fmt.Println(currentDirection, direction) layer := anymap{}
stacks := append(stack, Map(layer))
for currentDirection == direction { for currentDirection == direction {
resp, err := runVal(loop.body, append(stack, Map(anymap{ layer[loop.variable] = i
loop.variable: i, resp, err := runVal(loop.body, stacks, stacklevel+1)
})), stacklevel+1)
if err.EXISTS { if err.EXISTS {
return nil, err return nil, err
} }

View File

@@ -23,7 +23,7 @@ func convertToArgon(obj any) any {
case string: case string:
return ArString(x) return ArString(x)
case float64: case float64:
return Number(compiledNumber{value: newNumber().SetFloat64(x)}) return Number(x)
case bool: case bool:
return x return x
case nil: case nil:

View File

@@ -8,6 +8,6 @@ var e_RAT, _ = new(big.Rat).SetString("2.718281828459045235360287471352662497757
var e ArObject var e ArObject
func init() { func init() {
PI = Number(compiledNumber{PI_RAT}) PI = Number(PI_RAT)
e = Number(compiledNumber{e_RAT}) e = Number(e_RAT)
} }

View File

@@ -45,6 +45,9 @@ func numberToString(num *big.Rat, simplify bool) string {
return fmt.Sprint(x) return fmt.Sprint(x)
} }
var int64_max = new(big.Int).SetInt64(9223372036854775807)
var int64_min = new(big.Int).SetInt64(-9223372036854775808)
// returns translateNumber, success, error // returns translateNumber, success, error
func parseNumber(code UNPARSEcode) (compiledNumber, bool, ArErr, int) { func parseNumber(code UNPARSEcode) (compiledNumber, bool, ArErr, int) {
output, _ := new(big.Rat).SetString(strings.TrimSpace(code.code)) output, _ := new(big.Rat).SetString(strings.TrimSpace(code.code))
@@ -52,7 +55,22 @@ func parseNumber(code UNPARSEcode) (compiledNumber, bool, ArErr, int) {
return compiledNumber{output}, true, ArErr{}, 1 return compiledNumber{output}, true, ArErr{}, 1
} }
return compiledNumber{output.Num()}, true, ArErr{}, 1 output_big := output.Num()
if output_big.Cmp(int64_max) > 0 || output_big.Cmp(int64_min) < 0 {
return compiledNumber{output_big}, true, ArErr{}, 1
}
return compiledNumber{output_big.Int64()}, true, ArErr{}, 1
}
func isNumberInt64(num ArObject) bool {
if x, ok := num.obj["__value__"]; ok {
if _, ok := x.(int64); ok {
return true
}
}
return false
} }
type compiledNumber = struct { type compiledNumber = struct {
@@ -77,15 +95,17 @@ func numberToInt64(num ArObject) (int64, error) {
return floor(x).Num().Int64(), nil return floor(x).Num().Int64(), nil
case *big.Int: case *big.Int:
return x.Int64(), nil return x.Int64(), nil
case int64:
return x, nil
} }
return 0, fmt.Errorf("object cannot be converted to int64") return 0, fmt.Errorf("object cannot be converted to int64")
} }
func Int64ToNumber(num int64) ArObject { func Int64ToNumber(num int64) ArObject {
return Number(compiledNumber{big.NewInt(num)}) return Number(num)
} }
func CompareObjects(A ArObject, B ArObject) (ArObject, ArErr) { func CompareObjects(A ArObject, B ArObject) (ArObject, ArErr) {
if X, ok := A.obj["__compare__"]; ok { if X, ok := A.obj["__Compare__"]; ok {
resp, err := runCall(call{ resp, err := runCall(call{
Callable: X, Callable: X,
Args: []any{B}, Args: []any{B},
@@ -142,13 +162,11 @@ var _zero_Rat = big.NewRat(0, 1)
var _zero_Number ArObject var _zero_Number ArObject
func init() { func init() {
_zero_Number = Number(compiledNumber{_zero}) _zero_Number = Number(0)
_one_Number = Number(compiledNumber{_one}) _one_Number = Number(1)
} }
func Number(number compiledNumber) ArObject { func Number(value any) ArObject {
// copy value to new number
var value any = number.value
val := ArObject{ val := ArObject{
anymap{ anymap{
"__name__": "number", "__name__": "number",
@@ -160,6 +178,18 @@ func Number(number compiledNumber) ArObject {
value = x.Num() value = x.Num()
} }
case *big.Int: case *big.Int:
case int:
value = int64(x)
case int64:
case float64:
value = new(big.Rat).SetFloat64(x)
case float32:
value = new(big.Rat).SetFloat64(float64(x))
case string:
value, _ = new(big.Rat).SetString(x)
if value.(*big.Rat).IsInt() {
value = value.(*big.Rat).Num()
}
default: default:
panic("invalid number type") panic("invalid number type")
} }
@@ -168,6 +198,17 @@ func Number(number compiledNumber) ArObject {
switch CurrentNumber := value.(type) { switch CurrentNumber := value.(type) {
case *big.Int: case *big.Int:
_BigInt_logic(val, CurrentNumber)
case *big.Rat:
_BigRat_logic(val, CurrentNumber)
case int64:
_int64_logic(val, CurrentNumber)
}
return val
}
func _BigInt_logic(val ArObject, CurrentNumber *big.Int) {
val.obj["__string__"] = builtinFunc{ val.obj["__string__"] = builtinFunc{
"__string__", "__string__",
func(a ...any) (any, ArErr) { func(a ...any) (any, ArErr) {
@@ -207,9 +248,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{CurrentNumber.Cmp(ReceivingNumber)}), ArErr{} return Number(CurrentNumber.Cmp(ReceivingNumber)), ArErr{}
case int64:
return Number(CurrentNumber.Cmp(big.NewInt(ReceivingNumber))), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).SetInt(CurrentNumber).Cmp(ReceivingNumber)}), ArErr{} return Number(new(big.Rat).SetInt(CurrentNumber).Cmp(ReceivingNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -226,9 +269,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{ReceivingNumber.Cmp(CurrentNumber)}), ArErr{} return Number(ReceivingNumber.Cmp(CurrentNumber)), ArErr{}
case int64:
return Number(big.NewInt(ReceivingNumber).Cmp(CurrentNumber)), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{ReceivingNumber.Cmp(new(big.Rat).SetInt(CurrentNumber))}), ArErr{} return Number(ReceivingNumber.Cmp(new(big.Rat).SetInt(CurrentNumber))), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -254,7 +299,7 @@ func Number(number compiledNumber) ArObject {
for i := new(big.Int).SetInt64(2); i.Cmp(CurrentNumber) <= 0; i.Add(i, _one) { for i := new(big.Int).SetInt64(2); i.Cmp(CurrentNumber) <= 0; i.Add(i, _one) {
output.Mul(output, i) output.Mul(output, i)
} }
return Number(compiledNumber{output}), ArErr{} return Number(output), ArErr{}
}, },
} }
@@ -270,9 +315,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Int).Add(CurrentNumber, ReceivingNumber)}), ArErr{} return Number(new(big.Int).Add(CurrentNumber, ReceivingNumber)), ArErr{}
case int64:
return Number(new(big.Int).Add(CurrentNumber, big.NewInt(ReceivingNumber))), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Add(new(big.Rat).SetInt(CurrentNumber), ReceivingNumber)}), ArErr{} return Number(new(big.Rat).Add(new(big.Rat).SetInt(CurrentNumber), ReceivingNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -293,9 +340,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Int).Sub(CurrentNumber, ReceivingNumber)}), ArErr{} return Number(new(big.Int).Sub(CurrentNumber, ReceivingNumber)), ArErr{}
case int64:
return Number(new(big.Int).Sub(CurrentNumber, big.NewInt(ReceivingNumber))), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Sub(new(big.Rat).SetInt(CurrentNumber), ReceivingNumber)}), ArErr{} return Number(new(big.Rat).Sub(new(big.Rat).SetInt(CurrentNumber), ReceivingNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -312,9 +361,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Int).Sub(ReceivingNumber, CurrentNumber)}), ArErr{} return Number(new(big.Int).Sub(ReceivingNumber, CurrentNumber)), ArErr{}
case int64:
return Number(new(big.Int).Sub(big.NewInt(ReceivingNumber), CurrentNumber)), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Sub(ReceivingNumber, new(big.Rat).SetInt(CurrentNumber))}), ArErr{} return Number(new(big.Rat).Sub(ReceivingNumber, new(big.Rat).SetInt(CurrentNumber))), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -331,9 +382,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Int).Mul(CurrentNumber, ReceivingNumber)}), ArErr{} return Number(new(big.Int).Mul(CurrentNumber, ReceivingNumber)), ArErr{}
case int64:
return Number(new(big.Int).Mul(CurrentNumber, big.NewInt(ReceivingNumber))), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Mul(new(big.Rat).SetInt(CurrentNumber), ReceivingNumber)}), ArErr{} return Number(new(big.Rat).Mul(new(big.Rat).SetInt(CurrentNumber), ReceivingNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -354,9 +407,20 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Int).Quo(CurrentNumber, ReceivingNumber)}), ArErr{} if ReceivingNumber.Cmp(_zero) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Int).Quo(CurrentNumber, ReceivingNumber)), ArErr{}
case int64:
if ReceivingNumber == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Int).Quo(CurrentNumber, big.NewInt(ReceivingNumber))), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Quo(new(big.Rat).SetInt(CurrentNumber), ReceivingNumber)}), ArErr{} if ReceivingNumber.Cmp(_zero_Rat) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(new(big.Rat).SetInt(CurrentNumber), ReceivingNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -373,15 +437,27 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Int).Quo(ReceivingNumber, CurrentNumber)}), ArErr{} if CurrentNumber.Cmp(_zero) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Int).Quo(ReceivingNumber, CurrentNumber)), ArErr{}
case int64:
if CurrentNumber.Cmp(_zero) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Int).Quo(big.NewInt(ReceivingNumber), CurrentNumber)), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Quo(ReceivingNumber, new(big.Rat).SetInt(CurrentNumber))}), ArErr{} if CurrentNumber.Cmp(_zero) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(ReceivingNumber, new(big.Rat).SetInt(CurrentNumber))), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
} }
}
case *big.Rat: func _BigRat_logic(val ArObject, CurrentNumber *big.Rat) {
val.obj["__string__"] = builtinFunc{ val.obj["__string__"] = builtinFunc{
"__string__", "__string__",
func(a ...any) (any, ArErr) { func(a ...any) (any, ArErr) {
@@ -434,9 +510,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{CurrentNumber.Cmp(new(big.Rat).SetInt(ReceivingNumber))}), ArErr{} return Number(CurrentNumber.Cmp(new(big.Rat).SetInt(ReceivingNumber))), ArErr{}
case int64:
return Number(CurrentNumber.Cmp(new(big.Rat).SetInt64(ReceivingNumber))), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{CurrentNumber.Cmp(ReceivingNumber)}), ArErr{} return Number(CurrentNumber.Cmp(ReceivingNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -453,9 +531,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{CurrentNumber.Cmp(new(big.Rat).SetInt(ReceivingNumber))}), ArErr{} return Number(CurrentNumber.Cmp(new(big.Rat).SetInt(ReceivingNumber))), ArErr{}
case int64:
return Number(CurrentNumber.Cmp(new(big.Rat).SetInt64(ReceivingNumber))), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{CurrentNumber.Cmp(ReceivingNumber)}), ArErr{} return Number(CurrentNumber.Cmp(ReceivingNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -473,9 +553,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Rat).Add(CurrentNumber, new(big.Rat).SetInt(ReceivingNumber))}), ArErr{} return Number(new(big.Rat).Add(CurrentNumber, new(big.Rat).SetInt(ReceivingNumber))), ArErr{}
case int64:
return Number(new(big.Rat).Add(CurrentNumber, new(big.Rat).SetInt64(ReceivingNumber))), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Add(CurrentNumber, ReceivingNumber)}), ArErr{} return Number(new(big.Rat).Add(CurrentNumber, ReceivingNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -496,9 +578,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Rat).Sub(CurrentNumber, new(big.Rat).SetInt(ReceivingNumber))}), ArErr{} return Number(new(big.Rat).Sub(CurrentNumber, new(big.Rat).SetInt(ReceivingNumber))), ArErr{}
case int64:
return Number(new(big.Rat).Sub(CurrentNumber, new(big.Rat).SetInt64(ReceivingNumber))), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Sub(CurrentNumber, ReceivingNumber)}), ArErr{} return Number(new(big.Rat).Sub(CurrentNumber, ReceivingNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -515,9 +599,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Rat).Sub(new(big.Rat).SetInt(ReceivingNumber), CurrentNumber)}), ArErr{} return Number(new(big.Rat).Sub(new(big.Rat).SetInt(ReceivingNumber), CurrentNumber)), ArErr{}
case int64:
return Number(new(big.Rat).Sub(new(big.Rat).SetInt64(ReceivingNumber), CurrentNumber)), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Sub(ReceivingNumber, CurrentNumber)}), ArErr{} return Number(new(big.Rat).Sub(ReceivingNumber, CurrentNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -534,9 +620,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Rat).Mul(CurrentNumber, new(big.Rat).SetInt(ReceivingNumber))}), ArErr{} return Number(new(big.Rat).Mul(CurrentNumber, new(big.Rat).SetInt(ReceivingNumber))), ArErr{}
case int64:
return Number(new(big.Rat).Mul(CurrentNumber, new(big.Rat).SetInt64(ReceivingNumber))), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Mul(CurrentNumber, ReceivingNumber)}), ArErr{} return Number(new(big.Rat).Mul(CurrentNumber, ReceivingNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -553,9 +641,11 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Rat).Mul(new(big.Rat).SetInt(ReceivingNumber), CurrentNumber)}), ArErr{} return Number(new(big.Rat).Mul(new(big.Rat).SetInt(ReceivingNumber), CurrentNumber)), ArErr{}
case int64:
return Number(new(big.Rat).Mul(new(big.Rat).SetInt64(ReceivingNumber), CurrentNumber)), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Mul(ReceivingNumber, CurrentNumber)}), ArErr{} return Number(new(big.Rat).Mul(ReceivingNumber, CurrentNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -573,9 +663,20 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Rat).Quo(CurrentNumber, new(big.Rat).SetInt(ReceivingNumber))}), ArErr{} if ReceivingNumber.Cmp(_zero) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(CurrentNumber, new(big.Rat).SetInt(ReceivingNumber))), ArErr{}
case int64:
if ReceivingNumber == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(CurrentNumber, new(big.Rat).SetInt64(ReceivingNumber))), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Quo(CurrentNumber, ReceivingNumber)}), ArErr{} if ReceivingNumber.Cmp(_zero_Rat) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(CurrentNumber, ReceivingNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -592,9 +693,20 @@ func Number(number compiledNumber) ArObject {
a[0] = ArValidToAny(a[0]) a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) { switch ReceivingNumber := a[0].(type) {
case *big.Int: case *big.Int:
return Number(compiledNumber{new(big.Rat).Quo(new(big.Rat).SetInt(ReceivingNumber), CurrentNumber)}), ArErr{} if CurrentNumber.Cmp(_zero_Rat) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(new(big.Rat).SetInt(ReceivingNumber), CurrentNumber)), ArErr{}
case int64:
if CurrentNumber.Cmp(_zero_Rat) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(new(big.Rat).SetInt64(ReceivingNumber), CurrentNumber)), ArErr{}
case *big.Rat: case *big.Rat:
return Number(compiledNumber{new(big.Rat).Quo(ReceivingNumber, CurrentNumber)}), ArErr{} if CurrentNumber.Cmp(_zero_Rat) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(ReceivingNumber, CurrentNumber)), ArErr{}
} }
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true} return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
}, },
@@ -606,8 +718,301 @@ func Number(number compiledNumber) ArObject {
return nil, ArErr{"Runtime Error", "factorial of a non-integer number", 0, "", "", true} return nil, ArErr{"Runtime Error", "factorial of a non-integer number", 0, "", "", true}
}, },
} }
}
func _int64_logic(val ArObject, CurrentNumber int64) {
val.obj["__string__"] = builtinFunc{
"__string__",
func(a ...any) (any, ArErr) {
return ArString(fmt.Sprint(CurrentNumber)), ArErr{}
},
}
val.obj["__repr__"] = builtinFunc{
"__repr__",
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]) != "boolean" {
return nil, ArErr{"Type Error", "expected boolean, got " + typeof(a[0]), 0, "", "", true}
}
coloured := a[0].(bool)
output := []string{}
if coloured {
output = append(output, "\x1b[34;5;240m")
}
output = append(output, fmt.Sprint(CurrentNumber))
if coloured {
output = append(output, "\x1b[0m")
}
return ArString(strings.Join(output, "")), ArErr{}
},
} }
return val val.obj["__json__"] = builtinFunc{
"__json__",
val.obj["__string__"].(builtinFunc).FUNC,
}
val.obj["__Boolean__"] = builtinFunc{
"__Boolean__",
func(a ...any) (any, ArErr) {
return CurrentNumber != 0, ArErr{}
},
}
val.obj["__Compare__"] = builtinFunc{
"__Compare__",
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", "expected number, got " + typeof(a[0]), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) {
case *big.Int:
return Number(big.NewInt(CurrentNumber).Cmp(ReceivingNumber)), ArErr{}
case int64:
if CurrentNumber < ReceivingNumber {
return Number(-1), ArErr{}
}
if CurrentNumber > ReceivingNumber {
return Number(1), ArErr{}
}
return Number(0), ArErr{}
case *big.Rat:
return Number(new(big.Rat).SetInt64(CurrentNumber).Cmp(ReceivingNumber)), ArErr{}
}
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
},
}
val.obj["__PostCompare__"] = builtinFunc{
"__PostCompare__",
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", "expected number, got " + typeof(a[0]), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) {
case *big.Int:
return Number(ReceivingNumber.Cmp(big.NewInt(CurrentNumber))), ArErr{}
case int64:
if ReceivingNumber < CurrentNumber {
return Number(-1), ArErr{}
}
if ReceivingNumber > CurrentNumber {
return Number(1), ArErr{}
}
return Number(0), ArErr{}
case *big.Rat:
return Number(ReceivingNumber.Cmp(new(big.Rat).SetInt64(CurrentNumber))), ArErr{}
}
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
},
}
val.obj["__Add__"] = builtinFunc{
"__Add__",
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", "expected number, got " + typeof(a[0]), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) {
case *big.Int:
return Number(new(big.Int).Add(big.NewInt(CurrentNumber), ReceivingNumber)), ArErr{}
case int64:
calc := CurrentNumber + ReceivingNumber
// check for overflow
if (ReceivingNumber > 0 && CurrentNumber > 0 && calc < 0) || (ReceivingNumber < 0 && CurrentNumber < 0 && calc > 0) {
return Number(new(big.Int).Add(big.NewInt(CurrentNumber), big.NewInt(ReceivingNumber))), ArErr{}
}
return Number(calc), ArErr{}
case *big.Rat:
return Number(new(big.Rat).Add(new(big.Rat).SetInt64(CurrentNumber), ReceivingNumber)), ArErr{}
}
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
},
}
val.obj["__PostAdd__"] = builtinFunc{
"__PostAdd__",
val.obj["__Add__"].(builtinFunc).FUNC,
}
val.obj["__Subtract__"] = builtinFunc{
"__Subtract__",
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", "expected number, got " + typeof(a[0]), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) {
case *big.Int:
return Number(new(big.Int).Sub(big.NewInt(CurrentNumber), ReceivingNumber)), ArErr{}
case int64:
calc := CurrentNumber - ReceivingNumber
// check for overflow
if (ReceivingNumber > 0 && CurrentNumber < 0 && calc > 0) || (ReceivingNumber < 0 && CurrentNumber > 0 && calc < 0) {
return Number(new(big.Int).Sub(big.NewInt(CurrentNumber), big.NewInt(ReceivingNumber))), ArErr{}
}
return Number(calc), ArErr{}
case *big.Rat:
return Number(new(big.Rat).Sub(new(big.Rat).SetInt64(CurrentNumber), ReceivingNumber)), ArErr{}
}
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
},
}
val.obj["__PostSubtract__"] = builtinFunc{
"__PostSubtract__",
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", "expected number, got " + typeof(a[0]), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) {
case *big.Int:
return Number(new(big.Int).Sub(ReceivingNumber, big.NewInt(CurrentNumber))), ArErr{}
case int64:
calc := ReceivingNumber - CurrentNumber
// check for overflow
if (ReceivingNumber < 0 && CurrentNumber > 0 && calc > 0) || (ReceivingNumber > 0 && CurrentNumber < 0 && calc < 0) {
return Number(new(big.Int).Sub(big.NewInt(ReceivingNumber), big.NewInt(CurrentNumber))), ArErr{}
}
return Number(calc), ArErr{}
case *big.Rat:
return Number(new(big.Rat).Sub(ReceivingNumber, new(big.Rat).SetInt64(CurrentNumber))), ArErr{}
}
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
},
}
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", "expected number, got " + typeof(a[0]), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) {
case *big.Int:
return Number(new(big.Int).Mul(big.NewInt(CurrentNumber), ReceivingNumber)), ArErr{}
case int64:
calc := CurrentNumber * ReceivingNumber
// check for overflow
if ReceivingNumber != 0 && calc/ReceivingNumber != CurrentNumber {
return Number(new(big.Int).Mul(big.NewInt(CurrentNumber), big.NewInt(ReceivingNumber))), ArErr{}
}
return Number(calc), ArErr{}
case *big.Rat:
return Number(new(big.Rat).Mul(new(big.Rat).SetInt64(CurrentNumber), ReceivingNumber)), ArErr{}
}
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
},
}
val.obj["__PostMultiply__"] = builtinFunc{
"__PostMultiply__",
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", "expected number, got " + typeof(a[0]), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) {
case *big.Int:
return Number(new(big.Int).Mul(ReceivingNumber, big.NewInt(CurrentNumber))), ArErr{}
case int64:
calc := ReceivingNumber * CurrentNumber
// check for overflow
if CurrentNumber != 0 && calc/CurrentNumber != ReceivingNumber {
return Number(new(big.Int).Mul(big.NewInt(ReceivingNumber), big.NewInt(CurrentNumber))), ArErr{}
}
case *big.Rat:
return Number(new(big.Rat).Mul(ReceivingNumber, new(big.Rat).SetInt64(CurrentNumber))), ArErr{}
}
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
},
}
val.obj["__Divide__"] = builtinFunc{
"__Divide__",
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", "expected number, got " + typeof(a[0]), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) {
case *big.Int:
if ReceivingNumber.Cmp(big.NewInt(0)) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(new(big.Rat).SetInt64(CurrentNumber), new(big.Rat).SetInt(ReceivingNumber))), ArErr{}
case int64:
if ReceivingNumber == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(new(big.Rat).SetInt64(CurrentNumber), new(big.Rat).SetInt64(ReceivingNumber))), ArErr{}
case *big.Rat:
if ReceivingNumber.Cmp(_zero_Rat) == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(new(big.Rat).SetInt64(CurrentNumber), ReceivingNumber)), ArErr{}
}
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
},
}
val.obj["__PostDivide__"] = builtinFunc{
"__PostDivide__",
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", "expected number, got " + typeof(a[0]), 0, "", "", true}
}
a[0] = ArValidToAny(a[0])
switch ReceivingNumber := a[0].(type) {
case *big.Int:
if CurrentNumber == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
return Number(new(big.Rat).Quo(new(big.Rat).SetInt(ReceivingNumber), new(big.Rat).SetInt64(CurrentNumber))), ArErr{}
case int64:
if CurrentNumber == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
case *big.Rat:
if CurrentNumber == 0 {
return nil, ArErr{"Runtime Error", "division by zero", 0, "", "", true}
}
}
return nil, ArErr{"Type Error", "expected number, got " + typeof(a[0]), 0, "", "", true}
},
}
val.obj["__factorial__"] = builtinFunc{
"__factorial__",
func(a ...any) (any, ArErr) {
return nil, ArErr{"Runtime Error", "factorial of a non-integer number", 0, "", "", true}
},
}
} }

View File

@@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"math/big"
"reflect" "reflect"
) )
@@ -210,9 +209,7 @@ func runVal(line any, stack stack, stacklevel int) (any, ArErr) {
} }
return runTryCatch(x, stack, stacklevel+1) return runTryCatch(x, stack, stacklevel+1)
case compiledNumber: case compiledNumber:
return Number(x), ArErr{} return Number(x.value), ArErr{}
case *big.Rat, *big.Int:
return Number(compiledNumber{x}), ArErr{}
case bool, ArObject, nil, Callable, builtinFunc, anymap: case bool, ArObject, nil, Callable, builtinFunc, anymap:
return x, ArErr{} return x, ArErr{}
} }