diff --git a/.DS_Store b/.DS_Store index a358587..89b4296 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/src/brackets.go b/src/brackets.go index f36eb71..a406787 100644 --- a/src/brackets.go +++ b/src/brackets.go @@ -1,6 +1,8 @@ package main -import "strings" +import ( + "strings" +) var bracketsCompile = makeRegex(`( *)\((.|\n)+\)( *)`) @@ -17,7 +19,7 @@ func isBrackets(code UNPARSEcode) bool { func parseBrackets(code UNPARSEcode, index int, codeline []UNPARSEcode) (brackets, bool, ArErr, int) { resp, worked, err, i := translateVal(UNPARSEcode{ - code: strings.TrimSpace(code.code)[1 : len(code.code)-1], + code: strings.TrimSpace(code.code)[1 : len(code.code)-2], realcode: code.realcode, line: code.line, path: code.path, diff --git a/src/call.go b/src/call.go index 11869db..6930f37 100644 --- a/src/call.go +++ b/src/call.go @@ -84,7 +84,8 @@ func runCall(c call, stack stack) (any, ArErr) { for i, param := range x.params { level[param] = args[i] } - return runVal(x.run, append(stack, level)) + resp, err := runVal(x.run, append(stack, level)) + return resp, err } return nil, ArErr{"Runtime Error", "type '" + typeof(callable) + "' is not callable", c.line, c.path, c.code, true} } diff --git a/src/map.go b/src/map.go index bb2458f..befd415 100644 --- a/src/map.go +++ b/src/map.go @@ -68,6 +68,13 @@ func mapGet(r ArMapGet, stack stack) (any, ArErr) { } } +func classVal(r any) any { + if _, ok := r.(ArClass); ok { + return r.(ArClass).value + } + return r +} + func isMapGet(code UNPARSEcode) bool { return mapGetCompile.MatchString(code.code) } @@ -81,6 +88,6 @@ func mapGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapGet if !worked { return ArMapGet{}, false, err, i } - k := translateString{key, code.realcode, code.line} + k := key return ArMapGet{resp, k, code.line, code.realcode, code.path}, true, ArErr{}, 1 } diff --git a/src/number.go b/src/number.go index 17d1a77..55f6e2c 100644 --- a/src/number.go +++ b/src/number.go @@ -29,6 +29,11 @@ func isNumber(code UNPARSEcode) bool { return numberCompile.MatchString(code.code) || binaryCompile.MatchString(code.code) || hexCompile.MatchString(code.code) || octalCompile.MatchString(code.code) } +func isAnyNumber(x any) bool { + _, ok := x.(number) + return ok +} + // converts a number type to a string func numberToString(num number, fraction int) string { if fraction != 0 { @@ -44,7 +49,7 @@ func numberToString(num number, fraction int) string { denominator := split[1] super := []string{} - for i := 0; i < len(numerator); i++ { + for i := 0; i <= len(numerator); i++ { super = append(super, superscript[numerator[i]]) } sub := []string{} diff --git a/src/operations.go b/src/operations.go new file mode 100644 index 0000000..3c2e687 --- /dev/null +++ b/src/operations.go @@ -0,0 +1,138 @@ +package main + +import ( + "fmt" +) + +var operations = [][]string{ + {"-"}, + {"+"}, + {"/"}, + {"*"}, + {"%"}, + {"**", "^"}, + {"=="}, + {"!=", "≠"}, + {"<=", "≤"}, + {">=", "≥"}, + {"<"}, + {">"}, + {"&&", " and "}, + {"||", " or "}, +} + +type operationType struct { + operation int + values []any + line int + code string + path string +} + +func parseOperations(code UNPARSEcode, index int, codelines []UNPARSEcode) (operationType, bool, ArErr, int) { + for i := 0; i < len(operations); i++ { + values := []any{} + current := 0 + for l := 0; l < len(code.code); l++ { + for j := 0; j < len(operations[i]); j++ { + if len(code.code[l:]) >= len(operations[i][j]) && code.code[l:l+len(operations[i][j])] == operations[i][j] { + + resp, success, _, respindex := translateVal( + UNPARSEcode{ + code: code.code[current:l], + realcode: code.realcode, + line: code.line, + path: code.path, + }, index, codelines, false) + + if success { + index += respindex - 1 + values = append(values, resp) + current = l + len(operations[i][j]) + } + } + } + } + if len(values) > 0 { + resp, success, err, respindex := translateVal( + UNPARSEcode{ + code: code.code[current:], + realcode: code.realcode, + line: code.line, + path: code.path, + }, index, codelines, false) + if success { + index += respindex - 1 + values = append(values, resp) + return operationType{ + i, + values, + code.line, + code.realcode, + code.path, + }, true, err, index + } + return operationType{}, false, err, index + } + } + return operationType{}, false, ArErr{}, index +} + +func calcNegative(o operationType, stack stack) (number, ArErr) { + + resp, err := runVal( + o.values[0], + stack, + ) + resp = classVal(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.(number) + for i := 1; i < len(o.values); i++ { + resp, err := runVal( + o.values[i], + stack, + ) + resp = classVal(resp) + if err.EXISTS { + return nil, err + } + if isAnyNumber(resp) { + output = output.Sub(output, resp.(number)) + } else { + return nil, ArErr{ + "Runtime Error", + "Cannot subtract type '" + typeof(resp) + "'", + o.line, + o.path, + o.code, + true, + } + } + } + return output, ArErr{} +} + +func runOperation(o operationType, stack stack) (any, ArErr) { + switch o.operation { + case 0: + resp, err := calcNegative(o, stack) + if err.EXISTS { + return resp, err + } + return resp, ArErr{} + + } + panic("Unknown operation: " + fmt.Sprint(o.operation)) +} diff --git a/src/run.go b/src/run.go index 4cb683d..d7ae645 100644 --- a/src/run.go +++ b/src/run.go @@ -1,5 +1,10 @@ package main +import ( + "fmt" + "reflect" +) + // returns (number|string|nil), error func runVal(line any, stack stack) (any, ArErr) { if len(stack) > 500 { @@ -26,6 +31,7 @@ func runVal(line any, stack stack) (any, ArErr) { return setVariableValue(x, stack) case negative: resp, err := runVal(x.VAL, stack) + resp = classVal(resp) if err.EXISTS { return nil, err } @@ -40,7 +46,10 @@ func runVal(line any, stack stack) (any, ArErr) { } case brackets: return runVal(x.VAL, stack) + case operationType: + return runOperation(x, stack) } + fmt.Println("unreachable", reflect.TypeOf(line)) panic("unreachable") } diff --git a/src/string.go b/src/string.go index 0e386d1..d1bcb45 100644 --- a/src/string.go +++ b/src/string.go @@ -5,12 +5,6 @@ import ( "strings" ) -type translateString struct { - str string - code string - line int -} - var stringCompile = makeRegex("(( *)\"((\\\\([a-z\\\"'`]))|[^\\\"])*\"( *))|(( *)'((\\\\([a-z\\'\"`]))|[^\\'])*'( *))") func isString(code UNPARSEcode) bool { diff --git a/src/translate.go b/src/translate.go index 01b167d..e3560d8 100644 --- a/src/translate.go +++ b/src/translate.go @@ -7,7 +7,7 @@ type UNPARSEcode struct { path string } -// returns (translateNumber | translateString| nil), success, error, step +// returns (number | string | nil), success, error, step func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine bool) (any, bool, ArErr, int) { if isLine { if isBlank(code) { @@ -19,11 +19,18 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine b } } } - if isSetVariable(code) { - return parseSetVariable(code, index, codelines) - } else if isBrackets(code) { + if isBrackets(code) { return parseBrackets(code, index, codelines) - } else if isNumber(code) { + } else if isSetVariable(code) { + return parseSetVariable(code, index, codelines) + } + operation, worked, err, step := parseOperations(code, index, codelines) + if worked { + return operation, worked, err, step + } else if err.EXISTS { + return nil, worked, err, step + } + if isNumber(code) { return parseNumber(code) } else if isNegative(code) { return parseNegative(code, index, codelines) @@ -39,7 +46,7 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine b return nil, false, ArErr{"Syntax Error", "invalid syntax", code.line, code.path, code.realcode, true}, 1 } -// returns [](translateNumber | translateString), error +// returns [](number | string), error func translate(codelines []UNPARSEcode) ([]any, ArErr) { translated := []any{} for i := 0; i < len(codelines); { diff --git a/src/variable.go b/src/variable.go index db73446..d28dba1 100644 --- a/src/variable.go +++ b/src/variable.go @@ -116,7 +116,7 @@ func setVariableValue(v setVariable, stack stack) (any, ArErr) { for i := len(stack) - 1; i >= 0; i-- { if _, ok := stack[i][v.name]; ok { stack[i][v.name] = resp - return stack, ArErr{} + return resp, ArErr{} } } stack[len(stack)-1][v.name] = resp diff --git a/test.ar b/test.ar index 0a1c87d..e8bbb63 100644 --- a/test.ar +++ b/test.ar @@ -1,3 +1,4 @@ -let f(x) = x - -log(f(1)) \ No newline at end of file +y = time.now() +log('start') +time.snooze(1) +log(1e-250-1--1) \ No newline at end of file