diff --git a/src/array.go b/src/array.go index 8f5d65b..5855ead 100644 --- a/src/array.go +++ b/src/array.go @@ -80,7 +80,7 @@ func ArArray(arr []any) ArObject { if typeof(a[0]) != "number" { return nil, ArErr{ TYPE: "Type Error", - message: "dex must be a number", + message: "index must be a number", EXISTS: true, } } diff --git a/src/built-in-functions.go b/src/built-in-functions.go index 7700b4a..a73b4d4 100644 --- a/src/built-in-functions.go +++ b/src/built-in-functions.go @@ -48,26 +48,12 @@ func ArgonSqrt(a ...any) (any, ArErr) { return nil, ArErr{TYPE: "Runtime Error", message: "sqrt takes 1 argument", EXISTS: true} } - if typeof(a[0]) != "number" { - return nil, ArErr{TYPE: "Runtime Error", message: "sqrt takes a number not a '" + typeof(a[0]) + "'", + if _, ok := a[0].(ArObject); !ok { + return nil, ArErr{TYPE: "Runtime Error", message: "can't sqrt type '" + typeof(a[0]) + "'", EXISTS: true} } - - r := a[0].(number) - - if r.Sign() < 0 { - return nil, ArErr{TYPE: "Runtime Error", message: "sqrt takes a positive number", - EXISTS: true} + if sqrt_method, ok := a[0].(ArObject).obj["__sqrt__"]; ok { + return builtinCall(sqrt_method, []any{}) } - - var x big.Float - x.SetPrec(30) - x.SetRat(r) - - var s big.Float - s.SetPrec(15) - s.Sqrt(&x) - - r, _ = s.Rat(nil) - return r, ArErr{} + return nil, ArErr{TYPE: "Runtime Error", message: "can't sqrt type '" + typeof(a[0]) + "'"} } diff --git a/src/built-ins.go b/src/built-ins.go index 2ec296e..622f85c 100644 --- a/src/built-ins.go +++ b/src/built-ins.go @@ -11,7 +11,7 @@ func makeGlobal() ArObject { vars["env"] = env vars["term"] = ArTerm vars["ArgonVersion"] = ArString(VERSION) - vars["ArgonVersionNumber"] = newNumber().SetInt64(VERSION_NUM) + vars["ArgonVersionNumber"] = Number(VERSION_NUM) vars["number"] = builtinFunc{"number", ArgonNumber} vars["string"] = builtinFunc{"string", ArgonString} vars["socket"] = Map(anymap{ @@ -65,12 +65,8 @@ func makeGlobal() ArObject { } a[0] = ArValidToAny(a[0]) switch x := a[0].(type) { - case number: - if x.Denom().Cmp(_one_Rat.Denom()) != 0 { - return nil, ArErr{TYPE: "Type Error", message: "Cannot convert non-integer to hex", EXISTS: true} - } - n := x.Num().Int64() - return ArString(fmt.Sprintf("%x", n)), ArErr{} + case int64: + return ArString(fmt.Sprintf("%x", x)), ArErr{} } return nil, ArErr{TYPE: "Type Error", message: "Cannot convert '" + typeof(a[0]) + "' to hex", EXISTS: true} }} @@ -131,22 +127,21 @@ func makeGlobal() ArObject { return nil, ArErr{TYPE: "round", message: "round takes 1 argument", EXISTS: true} } - precision := newNumber() + var precision int64 = 0 if len(a) > 1 { + a[1] = ArValidToAny(a[1]) switch x := a[1].(type) { - case number: - if !x.IsInt() { - return nil, ArErr{TYPE: "Type Error", message: "Cannot round to '" + typeof(a[1]) + "'", EXISTS: true} - } + case int64: precision = x default: return nil, ArErr{TYPE: "Type Error", message: "Cannot round to '" + typeof(a[1]) + "'", EXISTS: true} } } - switch x := a[0].(type) { - case number: - return round(newNumber().Set(x), int(precision.Num().Int64())), ArErr{} + case ArObject: + if round_method, ok := x.obj["__round__"]; ok { + return builtinCall(round_method, []any{Number(precision)}) + } } return nil, ArErr{TYPE: "Type Error", message: "Cannot round '" + typeof(a[0]) + "'", EXISTS: true} }} @@ -156,8 +151,10 @@ func makeGlobal() ArObject { EXISTS: true} } switch x := a[0].(type) { - case number: - return floor(x), ArErr{} + case ArObject: + if floor_method, ok := x.obj["__floor__"]; ok { + return builtinCall(floor_method, []any{}) + } } return nil, ArErr{TYPE: "Type Error", message: "Cannot floor '" + typeof(a[0]) + "'", EXISTS: true} }} @@ -166,10 +163,11 @@ func makeGlobal() ArObject { return nil, ArErr{TYPE: "ceil", message: "ceil takes 1 argument", EXISTS: true} } - switch x := a[0].(type) { - case number: - return ceil(x), ArErr{} + case ArObject: + if ceil_method, ok := x.obj["__ceil__"]; ok { + return builtinCall(ceil_method, []any{}) + } } return nil, ArErr{TYPE: "Type Error", message: "Cannot ceil '" + typeof(a[0]) + "'", EXISTS: true} }} @@ -198,8 +196,6 @@ func makeGlobal() ArObject { EXISTS: true} } switch x := a[0].(type) { - case number: - return ArString(x.String()), ArErr{} case ArObject: if callable, ok := x.obj["__fraction__"]; ok { resp, err := runCall( @@ -239,9 +235,11 @@ func makeGlobal() ArObject { if len(a) == 0 { os.Exit(0) } + a[0] = ArValidToAny(a[0]) switch x := a[0].(type) { - case number: - os.Exit(int(floor(x).Num().Int64())) + case int64: + os.Exit(int(x)) + return nil, ArErr{} } os.Exit(0) return nil, ArErr{} @@ -267,7 +265,7 @@ func makeGlobal() ArObject { if len(x) != 1 { return nil, ArErr{TYPE: "ord", message: "ord takes a string with only one character, got " + fmt.Sprint(len(a)), EXISTS: true} } - return floor(newNumber().SetInt64(int64([]rune(x)[0]))), ArErr{} + return Number(int64([]rune(x)[0])), ArErr{} } return nil, ArErr{TYPE: "Type Error", message: "Cannot convert '" + typeof(a[0]) + "' to string", EXISTS: true} }} @@ -281,15 +279,27 @@ func makeGlobal() ArObject { if len(x) == 0 { return nil, ArErr{TYPE: "runtime Error", message: "max takes a non-empty array", EXISTS: true} } - var max number + var max ArObject for i, v := range x { - switch m := v.(type) { - case number: + switch x := v.(type) { + case ArObject: if i == 0 { - max = m + max = x } else { - if m.Cmp(max) == 1 { - max = m + compared, err := CompareObjects(max, x) + + if err.EXISTS { + return nil, err + } + + compared_int, Err := numberToInt64(compared) + + if Err != nil { + return nil, ArErr{TYPE: "Type Error", message: Err.Error(), EXISTS: true} + } + + if compared_int == 1 { + max = x } } } @@ -308,15 +318,27 @@ func makeGlobal() ArObject { if len(x) == 0 { return nil, ArErr{TYPE: "runtime Error", message: "max takes a non-empty array", EXISTS: true} } - var max number + var max ArObject for i, v := range x { - switch m := v.(type) { - case number: + switch x := v.(type) { + case ArObject: if i == 0 { - max = m + max = x } else { - if m.Cmp(max) == -1 { - max = m + compared, err := CompareObjects(max, x) + + if err.EXISTS { + return nil, err + } + + compared_int, Err := numberToInt64(compared) + + if Err != nil { + return nil, ArErr{TYPE: "Type Error", message: Err.Error(), EXISTS: true} + } + + if compared_int == -1 { + max = x } } } diff --git a/src/file.go b/src/file.go index 2db19e9..9fe9dac 100644 --- a/src/file.go +++ b/src/file.go @@ -153,11 +153,11 @@ func ArRead(args ...any) (any, ArErr) { if typeof(args[0]) != "number" { return ArObject{}, ArErr{TYPE: "Runtime Error", message: "buffer takes a number not type '" + typeof(args[0]) + "'", EXISTS: true} } - size := args[0].(number) - if size.Denom().Int64() != 1 { - return ArObject{}, ArErr{TYPE: "Runtime Error", message: "buffer takes an integer not type '" + typeof(args[0]) + "'", EXISTS: true} + size, err := numberToInt64(args[0].(ArObject)) + if err != nil { + return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true} } - buf := make([]byte, size.Num().Int64()) + buf := make([]byte, size) n, err := file.Read(buf) if err != nil { return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true} @@ -177,11 +177,11 @@ func ArRead(args ...any) (any, ArErr) { if typeof(args[0]) != "number" { return ArObject{}, ArErr{TYPE: "Runtime Error", message: "seek takes a number not type '" + typeof(args[0]) + "'", EXISTS: true} } - offset := args[0].(number) - if offset.Denom().Int64() != 1 { - return ArObject{}, ArErr{TYPE: "Runtime Error", message: "seek takes an integer not type '" + typeof(args[0]) + "'", EXISTS: true} + offset, Err := numberToInt64(args[0].(ArObject)) + if Err != nil { + return ArObject{}, ArErr{TYPE: "Runtime Error", message: Err.Error(), EXISTS: true} } - _, err := file.Seek(offset.Num().Int64(), io.SeekStart) + _, err := file.Seek(offset, io.SeekStart) if err != nil { return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true} } @@ -192,7 +192,7 @@ func ArRead(args ...any) (any, ArErr) { if err != nil { return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true} } - return newNumber().SetInt64(info.Size()), ArErr{} + return Number(info.Size()), ArErr{} }}, "ModTime": builtinFunc{"ModTime", func(...any) (any, ArErr) { info, err := file.Stat() diff --git a/src/logarithms.go b/src/logarithms.go index 2793c51..3db30ea 100644 --- a/src/logarithms.go +++ b/src/logarithms.go @@ -5,14 +5,24 @@ import ( "math" ) -var N = newNumber().SetInt64(1e6) +var N = Number(1e6) -func Ln(x number) number { - output := newNumber() - output.SetInt64(1) - output.Quo(output, N) +func Ln(x ArObject) (any, ArErr) { + var output any = Number(1) + var err ArErr + output, err = runOperation( + operationType{ + operation: 15, + values: []any{x}, + }, + stack{}, + 0, + ) + if err.EXISTS { + return nil, err + } - n1, _ := x.Float64() + n1, _ := x_rational.Float64() n2, _ := output.Float64() output = newNumber().SetFloat64(math.Pow(n1, n2)) output.Sub(output, newNumber().SetInt64(1)) @@ -34,10 +44,11 @@ func ArgonLn(a ...any) (any, ArErr) { return nil, ArErr{TYPE: "Runtime Error", message: "ln takes a positive number", EXISTS: true} } - return Ln(x), ArErr{} + return Ln(x) + } -var __ln10 = Ln(newNumber().SetInt64(10)) +var __ln10, _ = Ln(Number(10)) func ArgonLog(a ...any) (any, ArErr) { if len(a) != 1 { @@ -53,7 +64,7 @@ func ArgonLog(a ...any) (any, ArErr) { return nil, ArErr{TYPE: "Runtime Error", message: "log takes a positive number", EXISTS: true} } - return Ln(x).Quo(Ln(x), __ln10), ArErr{} + return Ln(x).Quo(Ln(x), __ln10) } func ArgonLogN(a ...any) (any, ArErr) { diff --git a/src/number.go b/src/number.go index d87b8c5..2866e9a 100644 --- a/src/number.go +++ b/src/number.go @@ -13,12 +13,12 @@ var hexCompile = makeRegex("( *)(-)?(0x[a-fA-F0-9]+(\\.[a-fA-F0-9]+)?)( *)") var octalCompile = makeRegex("( *)(-)?(0o[0-7]+(\\.[0-7]+)?(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)( *)") // a number type -type number = *big.Rat +// type number = *big.Rat // create a new number type -func newNumber() *big.Rat { - return new(big.Rat) -} +// func newNumber() *big.Rat { +// return new(big.Rat) +// } func isNumber(code UNPARSEcode) bool { return numberCompile.MatchString(code.code) || binaryCompile.MatchString(code.code) || hexCompile.MatchString(code.code) || octalCompile.MatchString(code.code)