From 42de489ca53113736bf297ac035e1f647781781c Mon Sep 17 00:00:00 2001 From: William Bell Date: Sat, 11 Mar 2023 12:22:33 +0000 Subject: [PATCH] create logarithm functions --- src/built-in-functions.go | 8 ++-- src/built-ins.go | 1 + src/call.go | 8 ++-- src/dowraps.go | 4 +- src/factorial.go | 12 +++-- src/jumpStatments.go | 4 +- src/letterseperateseperate.go | 2 +- src/logarithms.go | 86 +++++++++++++++++++++++++++++++++++ src/mapAndArray.go | 26 +++++------ src/maths.go | 3 ++ src/operations.go | 78 +++++++++++++++++++------------ src/run.go | 33 ++++++++------ src/shell.go | 22 ++++++++- src/thread.go | 2 +- src/translate.go | 4 ++ src/variable.go | 14 +++--- test.ar | 17 +++++-- 17 files changed, 235 insertions(+), 89 deletions(-) create mode 100644 src/logarithms.go diff --git a/src/built-in-functions.go b/src/built-in-functions.go index 4afd5cd..ebce748 100644 --- a/src/built-in-functions.go +++ b/src/built-in-functions.go @@ -24,7 +24,7 @@ func ArgonNumber(args ...any) (any, ArErr) { switch x := args[0].(type) { case string: if !numberCompile.MatchString(x) { - return nil, ArErr{TYPE: "Number Error", message: "Cannot convert type '" + x + "' to a number", EXISTS: true} + return nil, ArErr{TYPE: "Conversion Error", message: "Cannot convert " + anyToArgon(x, true, true, 3, 0, false, 0) + " to a number", EXISTS: true} } N, _ := newNumber().SetString(x) return N, ArErr{} @@ -44,7 +44,7 @@ func ArgonNumber(args ...any) (any, ArErr) { func ArgonSqrt(a ...any) (any, ArErr) { if len(a) == 0 { - return nil, ArErr{TYPE: "sqrt", message: "sqrt takes 1 argument", + return nil, ArErr{TYPE: "Runtime Error", message: "sqrt takes 1 argument", EXISTS: true} } if typeof(a[0]) != "number" { @@ -55,12 +55,12 @@ func ArgonSqrt(a ...any) (any, ArErr) { r := a[0].(number) if r.Sign() < 0 { - return nil, ArErr{TYPE: "sqrt", message: "sqrt takes a positive number", + return nil, ArErr{TYPE: "Runtime Error", message: "sqrt takes a positive number", EXISTS: true} } var x big.Float - x.SetPrec(30) // I didn't figure out the 'Prec' part correctly, read the docs more carefully than I did and experiement + x.SetPrec(30) x.SetRat(r) var s big.Float diff --git a/src/built-ins.go b/src/built-ins.go index bbf4f18..d06cef3 100644 --- a/src/built-ins.go +++ b/src/built-ins.go @@ -66,6 +66,7 @@ func init() { return nil, ArErr{TYPE: "TypeError", message: "Cannot create array from '" + typeof(a[0]) + "'", EXISTS: true} }} vars["maths"] = maths + vars["math"] = maths vars["time"] = ArTime vars["PI"] = PI vars["π"] = PI diff --git a/src/call.go b/src/call.go index 940f190..7961498 100644 --- a/src/call.go +++ b/src/call.go @@ -55,7 +55,7 @@ func parseCall(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, return call{callable: callable, args: arguments, line: code.line, code: code.realcode, path: code.path}, true, ArErr{}, 1 } -func runCall(c call, stack stack) (any, ArErr) { +func runCall(c call, stack stack, stacklevel int) (any, ArErr) { var callable any switch x := c.callable.(type) { case builtinFunc: @@ -63,7 +63,7 @@ func runCall(c call, stack stack) (any, ArErr) { case Callable: callable = x default: - callable_, err := runVal(c.callable, stack) + callable_, err := runVal(c.callable, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -72,7 +72,7 @@ func runCall(c call, stack stack) (any, ArErr) { args := []any{} level := append(stack, scope{}) for _, arg := range c.args { - resp, err := runVal(arg, level) + resp, err := runVal(arg, level, stacklevel+1) if err.EXISTS { return nil, err } @@ -93,7 +93,7 @@ func runCall(c call, stack stack) (any, ArErr) { for i, param := range x.params { level[param] = args[i] } - resp, err := runVal(x.run, append(x.stack, level)) + resp, err := runVal(x.run, append(x.stack, level), stacklevel+1) return openJump(resp), err } return nil, ArErr{"Runtime Error", "type '" + typeof(callable) + "' is not callable", c.line, c.path, c.code, true} diff --git a/src/dowraps.go b/src/dowraps.go index bc1fd81..21d98da 100644 --- a/src/dowraps.go +++ b/src/dowraps.go @@ -48,10 +48,10 @@ func parseDoWrap(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, boo return dowrap{run: translated, line: code.line, path: code.path, code: code.realcode}, true, ArErr{}, i - index } -func runDoWrap(d dowrap, stack stack) (any, ArErr) { +func runDoWrap(d dowrap, stack stack, stacklevel int) (any, ArErr) { newstack := append(stack, scope{}) for _, v := range d.run { - val, err := runVal(v, newstack) + val, err := runVal(v, newstack, stacklevel+1) if err.EXISTS { return nil, err } diff --git a/src/factorial.go b/src/factorial.go index d425aa4..b7f62dd 100644 --- a/src/factorial.go +++ b/src/factorial.go @@ -16,7 +16,7 @@ type factorial struct { func parseFactorial(code UNPARSEcode, index int, codeline []UNPARSEcode) (factorial, bool, ArErr, int) { trim := strings.TrimSpace(code.code) trim = trim[:len(trim)-1] - val, success, err, i := translateVal(UNPARSEcode{code: trim, realcode: code.realcode, line: 1, path: ""}, 0, []UNPARSEcode{}, 0) + val, success, err, i := translateVal(UNPARSEcode{code: trim, realcode: code.realcode, line: code.line, path: code.path}, index, codeline, 0) if !success { return factorial{}, false, err, i } @@ -29,7 +29,11 @@ func isFactorial(code UNPARSEcode) bool { } func fact(n number) number { - if n.Cmp(newNumber().SetInt64(0)) == 0 { + if n.Cmp(newNumber().SetInt64(1000)) >= 0 { + return infinity + } else if n.Cmp(newNumber().SetInt64(0)) == -1 { + return newNumber().SetInt64(0) + } else if n.Cmp(newNumber().SetInt64(0)) == 0 { return newNumber().SetInt64(1) } result := newNumber().SetInt64(1) @@ -39,8 +43,8 @@ func fact(n number) number { return result } -func runFactorial(f factorial, stack stack) (any, ArErr) { - val, err := runVal(f.value, stack) +func runFactorial(f factorial, stack stack, stacklevel int) (any, ArErr) { + val, err := runVal(f.value, stack, stacklevel+1) if err.EXISTS { return nil, err } diff --git a/src/jumpStatments.go b/src/jumpStatments.go index 27689d8..32f670b 100644 --- a/src/jumpStatments.go +++ b/src/jumpStatments.go @@ -40,10 +40,10 @@ func parseReturn(code UNPARSEcode, index int, codeline []UNPARSEcode) (CallJumpS }, worked, err, i } -func runJumpStatment(code CallJumpStatment, stack stack) (any, ArErr) { +func runJumpStatment(code CallJumpStatment, stack stack, stacklevel int) (any, ArErr) { var val any if code.value != nil { - v, err := runVal(code.value, stack) + v, err := runVal(code.value, stack, stacklevel+1) if err.EXISTS { return nil, err } diff --git a/src/letterseperateseperate.go b/src/letterseperateseperate.go index 6b5186f..9364364 100644 --- a/src/letterseperateseperate.go +++ b/src/letterseperateseperate.go @@ -18,7 +18,7 @@ func getValuesFromLetter(str string, splitstr string, index int, codelines []UNP arguments = append(arguments, nil) temp = []string{} } else { - resp, worked, _, _ := translateVal(UNPARSEcode{code: test, realcode: codelines[index].realcode, line: index + 1, path: codelines[index].path}, index, codelines, 0) + resp, worked, _, _ := translateVal(UNPARSEcode{code: test, realcode: codelines[index].realcode, line: index, path: codelines[index].path}, index, codelines, 0) if worked { arguments = append(arguments, resp) temp = []string{} diff --git a/src/logarithms.go b/src/logarithms.go new file mode 100644 index 0000000..0442f6d --- /dev/null +++ b/src/logarithms.go @@ -0,0 +1,86 @@ +package main + +import ( + "fmt" + "math" +) + +var N = newNumber().SetInt64(1e10) + +func Ln(x number) number { + output := newNumber() + output.SetInt64(1) + output.Quo(output, N) + + n1, _ := x.Float64() + n2, _ := output.Float64() + output = newNumber().SetFloat64(math.Pow(n1, n2)) + if output == nil { + output = infinity + } + output.Sub(output, newNumber().SetInt64(1)) + output.Mul(output, N) + return output +} + +func ArgonLn(a ...any) (any, ArErr) { + if len(a) != 0 { + return nil, ArErr{TYPE: "Runtime Error", message: "ln takes 1 argument, got " + fmt.Sprint(len(a)), + EXISTS: true} + } + if typeof(a[0]) != "number" { + return nil, ArErr{TYPE: "Runtime Error", message: "ln takes a number not a '" + typeof(a[0]) + "'", + EXISTS: true} + } + x := a[0].(number) + if x.Sign() <= 0 { + return nil, ArErr{TYPE: "Runtime Error", message: "ln takes a positive number", + EXISTS: true} + } + return Ln(x), ArErr{} +} + +var __ln10 = Ln(newNumber().SetInt64(10)) + +func ArgonLog(a ...any) (any, ArErr) { + if len(a) != 1 { + return nil, ArErr{TYPE: "Runtime Error", message: "log takes 1 argument, got " + fmt.Sprint(len(a)), + EXISTS: true} + } + if typeof(a[0]) != "number" { + return nil, ArErr{TYPE: "Runtime Error", message: "log takes a number not a '" + typeof(a[0]) + "'", + EXISTS: true} + } + x := a[0].(number) + if x.Sign() <= 0 { + return nil, ArErr{TYPE: "Runtime Error", message: "log takes a positive number", + EXISTS: true} + } + return Ln(x).Quo(Ln(x), __ln10), ArErr{} +} + +func ArgonLogN(a ...any) (any, ArErr) { + if len(a) != 2 { + return nil, ArErr{TYPE: "Runtime Error", message: "logN takes 2 argument, got " + fmt.Sprint(len(a)), + EXISTS: true} + } + if typeof(a[0]) != "number" { + return nil, ArErr{TYPE: "Runtime Error", message: "logN takes a number not a '" + typeof(a[0]) + "'", + EXISTS: true} + } + if typeof(a[1]) != "number" { + return nil, ArErr{TYPE: "Runtime Error", message: "logN takes a number not a '" + typeof(a[0]) + "'", + EXISTS: true} + } + N := a[0].(number) + if N.Sign() <= 0 { + return nil, ArErr{TYPE: "Runtime Error", message: "logN takes a positive number", + EXISTS: true} + } + x := a[1].(number) + if x.Sign() <= 0 { + return nil, ArErr{TYPE: "Runtime Error", message: "logN takes a positive number", + EXISTS: true} + } + return Ln(x).Quo(Ln(x), Ln(N)), ArErr{} +} diff --git a/src/mapAndArray.go b/src/mapAndArray.go index f1c2ce6..1c875e7 100644 --- a/src/mapAndArray.go +++ b/src/mapAndArray.go @@ -28,8 +28,8 @@ type ArMapGet struct { path string } -func mapGet(r ArMapGet, stack stack) (any, ArErr) { - resp, err := runVal(r.VAL, stack) +func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) { + resp, err := runVal(r.VAL, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -45,7 +45,7 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { true, } } - key, err := runVal(r.start, stack) + key, err := runVal(r.start, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -67,7 +67,7 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { step := 1 if !r.index { - key, err := runVal(r.start, stack) + key, err := runVal(r.start, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -76,7 +76,7 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { } } if r.start != nil { - sindex, err := runVal(r.start, stack) + sindex, err := runVal(r.start, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -105,7 +105,7 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { endindex = startindex + 1 } if r.end != nil { - eindex, err := runVal(r.end, stack) + eindex, err := runVal(r.end, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -135,7 +135,7 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { endindex = len(m) } if r.step != nil { - step, err := runVal(r.step, stack) + step, err := runVal(r.step, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -214,7 +214,7 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { true, } } - key, err := runVal(r.start, stack) + key, err := runVal(r.start, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -235,7 +235,7 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { step := 1 if !r.index { - key, err := runVal(r.start, stack) + key, err := runVal(r.start, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -244,7 +244,7 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { } } if r.start != nil { - sindex, err := runVal(r.start, stack) + sindex, err := runVal(r.start, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -273,7 +273,7 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { endindex = startindex + 1 } if r.end != nil { - eindex, err := runVal(r.end, stack) + eindex, err := runVal(r.end, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -303,7 +303,7 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { endindex = len(m) } if r.step != nil { - step, err := runVal(r.step, stack) + step, err := runVal(r.step, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -373,7 +373,7 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { return string(([]byte(m))[startindex:endindex:step]), ArErr{} } - key, err := runVal(r.start, stack) + key, err := runVal(r.start, stack, stacklevel+1) if err.EXISTS { return nil, err } diff --git a/src/maths.go b/src/maths.go index e375c79..f4c8d3e 100644 --- a/src/maths.go +++ b/src/maths.go @@ -61,4 +61,7 @@ var maths = ArMap{ return nil, ArErr{TYPE: "TypeError", message: "Cannot ceil '" + typeof(a[0]) + "'", EXISTS: true} }}, "sqrt": builtinFunc{"sqrt", ArgonSqrt}, + "ln": builtinFunc{"ln", ArgonLn}, + "log": builtinFunc{"log", ArgonLog}, + "logN": builtinFunc{"logN", ArgonLogN}, } diff --git a/src/operations.go b/src/operations.go index ab998ed..388df97 100644 --- a/src/operations.go +++ b/src/operations.go @@ -105,7 +105,7 @@ func parseOperations(code UNPARSEcode, index int, codelines []UNPARSEcode) (oper return operationType{}, false, ArErr{}, 0 } -func compareValues(o operationType, stack stack) (bool, ArErr) { +func compareValues(o operationType, stack stack, stacklevel int) (bool, ArErr) { if len(o.values) != 2 { return false, ArErr{ "Runtime Error", @@ -119,6 +119,7 @@ func compareValues(o operationType, stack stack) (bool, ArErr) { resp, err := runVal( o.values[0], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -128,6 +129,7 @@ func compareValues(o operationType, stack stack) (bool, ArErr) { resp2, err := runVal( o.values[1], stack, + stacklevel+1, ) resp2 = classVal(resp2) if err.EXISTS { @@ -198,11 +200,12 @@ func compareValues(o operationType, stack stack) (bool, ArErr) { } } -func calcNegative(o operationType, stack stack) (number, ArErr) { +func calcNegative(o operationType, stack stack, stacklevel int) (number, ArErr) { resp, err := runVal( o.values[0], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -223,6 +226,7 @@ func calcNegative(o operationType, stack stack) (number, ArErr) { resp, err := runVal( o.values[i], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -244,11 +248,12 @@ func calcNegative(o operationType, stack stack) (number, ArErr) { return output, ArErr{} } -func calcDivide(o operationType, stack stack) (number, ArErr) { +func calcDivide(o operationType, stack stack, stacklevel int) (number, ArErr) { resp, err := runVal( o.values[0], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -269,6 +274,7 @@ func calcDivide(o operationType, stack stack) (number, ArErr) { resp, err := runVal( o.values[i], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -290,11 +296,12 @@ func calcDivide(o operationType, stack stack) (number, ArErr) { return output, ArErr{} } -func calcAdd(o operationType, stack stack) (any, ArErr) { +func calcAdd(o operationType, stack stack, stacklevel int) (any, ArErr) { resp, err := runVal( o.values[0], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -310,6 +317,7 @@ func calcAdd(o operationType, stack stack) (any, ArErr) { resp, err := runVal( o.values[i], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -328,11 +336,12 @@ func calcAdd(o operationType, stack stack) (any, ArErr) { return output, ArErr{} } -func calcMul(o operationType, stack stack) (any, ArErr) { +func calcMul(o operationType, stack stack, stacklevel int) (any, ArErr) { resp, err := runVal( o.values[0], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -348,6 +357,7 @@ func calcMul(o operationType, stack stack) (any, ArErr) { resp, err := runVal( o.values[i], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -375,12 +385,13 @@ func calcMul(o operationType, stack stack) (any, ArErr) { return output, ArErr{} } -func calcAnd(o operationType, stack stack) (any, ArErr) { +func calcAnd(o operationType, stack stack, stacklevel int) (any, ArErr) { var output any = false for i := 0; i < len(o.values); i++ { resp, err := runVal( o.values[i], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -394,12 +405,13 @@ func calcAnd(o operationType, stack stack) (any, ArErr) { return output, ArErr{} } -func calcOr(o operationType, stack stack) (any, ArErr) { +func calcOr(o operationType, stack stack, stacklevel int) (any, ArErr) { var output any = false for i := 0; i < len(o.values); i++ { resp, err := runVal( o.values[i], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -422,7 +434,7 @@ func stringInSlice(a any, list []any) bool { return false } -func calcIn(o operationType, stack stack) (bool, ArErr) { +func calcIn(o operationType, stack stack, stacklevel int) (bool, ArErr) { if len(o.values) != 2 { return false, ArErr{ "Runtime Error", @@ -436,6 +448,7 @@ func calcIn(o operationType, stack stack) (bool, ArErr) { resp, err := runVal( o.values[0], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -445,6 +458,7 @@ func calcIn(o operationType, stack stack) (bool, ArErr) { resp2, err := runVal( o.values[1], stack, + stacklevel+1, ) resp2 = classVal(resp2) if err.EXISTS { @@ -481,10 +495,11 @@ func equals(a any, b any) bool { return reflect.DeepEqual(a, b) } -func calcMod(o operationType, stack stack) (number, ArErr) { +func calcMod(o operationType, stack stack, stacklevel int) (number, ArErr) { resp, err := runVal( o.values[0], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -505,6 +520,7 @@ func calcMod(o operationType, stack stack) (number, ArErr) { resp, err := runVal( o.values[i], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -528,17 +544,18 @@ func calcMod(o operationType, stack stack) (number, ArErr) { return output, ArErr{} } -func calcIntDiv(o operationType, stack stack) (number, ArErr) { - resp, err := calcDivide(o, stack) +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 calcPower(o operationType, stack stack) (number, ArErr) { +func calcPower(o operationType, stack stack, stacklevel int) (number, ArErr) { resp, err := runVal( o.values[0], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -559,6 +576,7 @@ func calcPower(o operationType, stack stack) (number, ArErr) { resp, err := runVal( o.values[i], stack, + stacklevel+1, ) resp = classVal(resp) if err.EXISTS { @@ -585,44 +603,44 @@ func calcPower(o operationType, stack stack) (number, ArErr) { return output, ArErr{} } -func runOperation(o operationType, stack stack) (any, ArErr) { +func runOperation(o operationType, stack stack, stacklevel int) (any, ArErr) { switch o.operation { case 0: - return calcAnd(o, stack) + return calcAnd(o, stack, stacklevel+1) case 1: - return calcOr(o, stack) + return calcOr(o, stack, stacklevel+1) case 2: - resp, err := calcIn(o, stack) + resp, err := calcIn(o, stack, stacklevel+1) resp = !resp return resp, err case 3: - return calcIn(o, stack) + return calcIn(o, stack, stacklevel+1) case 4: - return compareValues(o, stack) + return compareValues(o, stack, stacklevel+1) case 5: - return compareValues(o, stack) + return compareValues(o, stack, stacklevel+1) case 6: - return compareValues(o, stack) + return compareValues(o, stack, stacklevel+1) case 7: - return compareValues(o, stack) + return compareValues(o, stack, stacklevel+1) case 8: - return compareValues(o, stack) + return compareValues(o, stack, stacklevel+1) case 9: - return compareValues(o, stack) + return compareValues(o, stack, stacklevel+1) case 10: - return calcAdd(o, stack) + return calcAdd(o, stack, stacklevel+1) case 11: - return calcNegative(o, stack) + return calcNegative(o, stack, stacklevel+1) case 12: - return calcMul(o, stack) + return calcMul(o, stack, stacklevel+1) case 13: - return calcMod(o, stack) + return calcMod(o, stack, stacklevel+1) case 14: - return calcIntDiv(o, stack) + return calcIntDiv(o, stack, stacklevel+1) case 15: - return calcDivide(o, stack) + return calcDivide(o, stack, stacklevel+1) case 16: - return calcPower(o, stack) + return calcPower(o, stack, stacklevel+1) } panic("Unknown operation: " + fmt.Sprint(o.operation)) diff --git a/src/run.go b/src/run.go index e67ed83..cd5cf2e 100644 --- a/src/run.go +++ b/src/run.go @@ -6,11 +6,14 @@ import ( ) // returns (number|string|nil), error -func runVal(line any, stack stack) (any, ArErr) { - if len(stack) > 500 { +func runVal(line any, stack stack, stacklevel int) (any, ArErr) { + if stacklevel > 10000 { return nil, ArErr{ - TYPE: "Stack overflow", - message: "the stack has exceeded 500 levels", + TYPE: "RuntimeError", + message: "stack overflow", + line: 0, + path: "", + code: "", EXISTS: true, } } @@ -20,19 +23,19 @@ func runVal(line any, stack stack) (any, ArErr) { case string: return x, ArErr{} case call: - return runCall(x, stack) + return runCall(x, stack, stacklevel+1) case factorial: - return runFactorial(x, stack) + return runFactorial(x, stack, stacklevel+1) case accessVariable: return readVariable(x, stack) case ArMapGet: - return mapGet(x, stack) + return mapGet(x, stack, stacklevel+1) case ArClass: return x.MAP, ArErr{} case setVariable: - return setVariableValue(x, stack) + return setVariableValue(x, stack, stacklevel+1) case negative: - resp, err := runVal(x.VAL, stack) + resp, err := runVal(x.VAL, stack, stacklevel+1) resp = classVal(resp) if err.EXISTS { return nil, err @@ -47,15 +50,15 @@ func runVal(line any, stack stack) (any, ArErr) { EXISTS: true, } case brackets: - return runVal(x.VAL, stack) + return runVal(x.VAL, stack, stacklevel+1) case operationType: - return runOperation(x, stack) + return runOperation(x, stack, stacklevel+1) case dowrap: - return runDoWrap(x, stack) + return runDoWrap(x, stack, stacklevel+1) case CallJumpStatment: - return runJumpStatment(x, stack) + return runJumpStatment(x, stack, stacklevel+1) case ArDelete: - return runDelete(x, stack) + return runDelete(x, stack, stacklevel+1) } fmt.Println("unreachable", reflect.TypeOf(line)) panic("unreachable") @@ -65,7 +68,7 @@ func runVal(line any, stack stack) (any, ArErr) { func run(translated []any, stack stack) (any, ArErr, any) { var output any = nil for _, val := range translated { - val, err := runVal(val, stack) + val, err := runVal(val, stack, 0) output = val if err.EXISTS { return nil, err, output diff --git a/src/shell.go b/src/shell.go index 0be6383..c68a32c 100644 --- a/src/shell.go +++ b/src/shell.go @@ -6,6 +6,12 @@ import ( "os/signal" ) +var endingWithDoCompiled = makeRegex(`.*do( )*`) + +func isEndingWithDo(str string) bool { + return endingWithDoCompiled.MatchString(str) +} + func shell() { global := stack{vars, scope{}} c := make(chan os.Signal, 1) @@ -19,9 +25,23 @@ func shell() { } }() for { + indo := false + totranslate := []UNPARSEcode{} code := input("\x1b[38;5;240m>>> \x1b[0m\x1b[1;5;240m") fmt.Print("\x1b[0m") - translated, translationerr := translate([]UNPARSEcode{{code, code, 1, ""}}) + if isEndingWithDo(code) { + indo = true + } + totranslate = append(totranslate, UNPARSEcode{code, code, 1, ""}) + for i := 2; indo; i++ { + code := input("\x1b[38;5;240m... \x1b[0m\x1b[1;5;240m") + fmt.Print("\x1b[0m") + totranslate = append(totranslate, UNPARSEcode{code, code, i, ""}) + if code == "" { + indo = false + } + } + translated, translationerr := translate(totranslate) count := len(translated) if translationerr.EXISTS { panicErr(translationerr) diff --git a/src/thread.go b/src/thread.go index 172f91e..3681772 100644 --- a/src/thread.go +++ b/src/thread.go @@ -29,7 +29,7 @@ func ArThread(args ...any) (any, ArErr) { hasrun = true wg.Add(1) go func() { - resp, err = runCall(call{tocall, []any{}, "", 0, ""}, currentscope) + resp, err = runCall(call{tocall, []any{}, "", 0, ""}, currentscope, 0) wg.Done() }() return nil, ArErr{} diff --git a/src/translate.go b/src/translate.go index ecec099..beb8a9e 100644 --- a/src/translate.go +++ b/src/translate.go @@ -96,6 +96,10 @@ func translate(codelines []UNPARSEcode) ([]any, ArErr) { return nil, ArErr{"Syntax Error", "invalid indent", codelines[i].line, codelines[i].path, codelines[i].realcode, true} } val, _, err, step := translateVal(codelines[i], i, codelines, 2) + switch val.(type) { + case CallJumpStatment: + return nil, ArErr{"Runtime Error", "Jump statment at top level", codelines[i].line, codelines[i].path, codelines[i].realcode, true} + } i += step if err.EXISTS { return nil, err diff --git a/src/variable.go b/src/variable.go index 182168e..99d2c63 100644 --- a/src/variable.go +++ b/src/variable.go @@ -184,12 +184,12 @@ func parseAutoAsignVariable(code UNPARSEcode, index int, lines []UNPARSEcode, is return setVariable{TYPE: "auto", toset: toset, value: value, function: function, params: params, line: code.line, code: code.code, path: code.path}, true, ArErr{}, i + namei - 1 } -func setVariableValue(v setVariable, stack stack) (any, ArErr) { +func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) { var resp any if v.function { resp = Callable{v.params, v.value, v.code, stack, v.line} } else { - respp, err := runVal(v.value, stack) + respp, err := runVal(v.value, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -212,11 +212,11 @@ func setVariableValue(v setVariable, stack stack) (any, ArErr) { } stack[len(stack)-1][x.name] = resp case ArMapGet: - respp, err := runVal(x.VAL, stack) + respp, err := runVal(x.VAL, stack, stacklevel+1) if err.EXISTS { return nil, err } - key, err := runVal(x.start, stack) + key, err := runVal(x.start, stack, stacklevel+1) if err.EXISTS { return nil, err } @@ -251,7 +251,7 @@ func parseDelete(code UNPARSEcode, index int, lines []UNPARSEcode) (ArDelete, bo }, true, ArErr{}, i } -func runDelete(d ArDelete, stack stack) (any, ArErr) { +func runDelete(d ArDelete, stack stack, stacklevel int) (any, ArErr) { switch x := d.value.(type) { case accessVariable: for i := len(stack) - 1; i >= 0; i-- { @@ -262,11 +262,11 @@ func runDelete(d ArDelete, stack stack) (any, ArErr) { } return nil, ArErr{"Runtime Error", "variable \"" + x.name + "\" does not exist", d.line, d.path, d.code, true} case ArMapGet: - respp, err := runVal(x.VAL, stack) + respp, err := runVal(x.VAL, stack, stacklevel+1) if err.EXISTS { return nil, err } - key, err := runVal(x.start, stack) + key, err := runVal(x.start, stack, stacklevel+1) if err.EXISTS { return nil, err } diff --git a/test.ar b/test.ar index 276da58..ecab21b 100644 --- a/test.ar +++ b/test.ar @@ -1,6 +1,13 @@ -f(x) = do - y = number(input("what number? ")) - return (z) = do - return maths.round(z) * y * x +let ln(x) = do + let n = 1e10 + return n * ((x^(1/n)) - 1) -term.log(f(5)(70)) \ No newline at end of file +let __ln10cache = ln(10) + +let log(x) = do + return ln(x) / __ln10cache + +let logN(n,x) = do + return ln(x) / ln(n) + +term.log(log(1000)) \ No newline at end of file