From 8f51b24c7ce5000143efa2e0a64028984302eabb Mon Sep 17 00:00:00 2001 From: William Bell Date: Wed, 19 Feb 2025 02:31:32 +0000 Subject: [PATCH] fix brainfuck, allow multiplying array by int, and fix incorrect error message in ord --- server_test/app.ar | 9 ++++++ src/array.go | 25 +++++++++++++++- src/buffer.go | 4 +-- src/built-ins.go | 2 +- src/string.go | 4 +-- tests/brainfuck.ar | 74 +++++++++++++++++++++++++++------------------- 6 files changed, 81 insertions(+), 37 deletions(-) create mode 100644 server_test/app.ar diff --git a/server_test/app.ar b/server_test/app.ar new file mode 100644 index 0000000..620d037 --- /dev/null +++ b/server_test/app.ar @@ -0,0 +1,9 @@ +import "http.ar" as http + +let server = http.server() + +let home(req,res) = do + res.send("hello world") +server.get("/", home) + +server.run() \ No newline at end of file diff --git a/src/array.go b/src/array.go index cde4228..d6ce27f 100644 --- a/src/array.go +++ b/src/array.go @@ -61,6 +61,29 @@ func ArArray(arr []any) ArObject { return nil, ArErr{} }, } + 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", "cannot multiply array by " + typeof(a[0]), 0, "", "", true} + } + n := a[0].(number) + if !n.IsInt() { + return nil, ArErr{"Value Error", "cannot multiply array by float", 0, "", "", true} + } + if n.Sign() < 0 { + return nil, ArErr{"Value Error", "cannot multiply array by negative number", 0, "", "", true} + } + size := int(n.Num().Int64()) + retval := make([]any, 0, len(arr)*size) + for i := 0; i < size; i++ { + retval = append(retval, arr...) + } + return ArArray(retval), ArErr{} + }} val.obj["__getindex__"] = builtinFunc{ "__getindex__", func(a ...any) (any, ArErr) { @@ -474,7 +497,7 @@ func ArArray(arr []any) ArObject { } if len(arr) == 0 { return nil, ArErr{ - TYPE: "ValueError", + TYPE: "Value Error", message: "array is empty", EXISTS: true, } diff --git a/src/buffer.go b/src/buffer.go index 9538de5..ec5d50c 100644 --- a/src/buffer.go +++ b/src/buffer.go @@ -53,7 +53,7 @@ func ArByte(Byte byte) ArObject { n := x.Num().Int64() if n > 255 || n < 0 { return nil, ArErr{ - TYPE: "ValueError", + TYPE: "Value Error", message: "expected number between 0 and 255, got " + fmt.Sprint(floor(x).Num().Int64()), EXISTS: true, } @@ -62,7 +62,7 @@ func ArByte(Byte byte) ArObject { case string: if len(x) != 1 { return nil, ArErr{ - TYPE: "ValueError", + TYPE: "Value Error", message: "expected string of length 1, got " + fmt.Sprint(len(x)), EXISTS: true, } diff --git a/src/built-ins.go b/src/built-ins.go index 730916b..3db43fb 100644 --- a/src/built-ins.go +++ b/src/built-ins.go @@ -267,7 +267,7 @@ func makeGlobal() ArObject { switch x := a[0].(type) { case string: 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 nil, ArErr{TYPE: "ord", message: "ord takes a string with only one character, got " + fmt.Sprint(len(x)), EXISTS: true} } return floor(newNumber().SetInt64(int64([]rune(x)[0]))), ArErr{} } diff --git a/src/string.go b/src/string.go index 11e785e..ad7a1d5 100644 --- a/src/string.go +++ b/src/string.go @@ -629,10 +629,10 @@ func ArString(str string) ArObject { } n := a[0].(number) if !n.IsInt() { - return nil, ArErr{"ValueError", "cannot multiply string by float", 0, "", "", true} + return nil, ArErr{"Value Error", "cannot multiply string by float", 0, "", "", true} } if n.Sign() < 0 { - return nil, ArErr{"ValueError", "cannot multiply string by negative number", 0, "", "", true} + return nil, ArErr{"Value Error", "cannot multiply string by negative number", 0, "", "", true} } return strings.Repeat(str, int(n.Num().Int64())), ArErr{} }} diff --git a/tests/brainfuck.ar b/tests/brainfuck.ar index ffd06f0..3da3826 100644 --- a/tests/brainfuck.ar +++ b/tests/brainfuck.ar @@ -1,33 +1,45 @@ -let interpret(code) = do - memory = map() +let brainfuck(INPUT) = do + memory = [0] * 30*1000 pointer = 0 - code_ptr = 0 - loops = [] + output = "" + i = 0 + while (i < INPUT.length) do + if (INPUT[i] == ">") do + pointer += 1 + else if (INPUT[i] == "<") do + pointer -= 1 + else if (INPUT[i] == "+") do + memory[pointer] += 1 + else if (INPUT[i] == "-") do + memory[pointer] -= 1 + else if (INPUT[i] == ".") do + output += chr(memory[pointer]) + else if (INPUT[i] == ",") do + memory[pointer] = ord(input()) + else if (INPUT[i] == "[") do + if (memory[pointer] == 0) do + count = 1 + while (count > 0) do + i += 1 + if (INPUT[i] == "[") do + count += 1 + else if (INPUT[i] == "]") do + count -= 1 + else if (INPUT[i] == "]") do + if (memory[pointer] != 0) do + count = 1 + while (count > 0) do + i -= 1 + if (INPUT[i] == "]") do + count += 1 + else if (INPUT[i] == "[") do + count -= 1 + else do + pass + i += 1 + term.print(memory) + return output - while (code_ptr < code.length) do - command = code[code_ptr] - - if (command == '>') pointer = pointer + 1 - else if (command == '<') pointer = pointer - 1 - else if (command == '+') do - if (pointer not in memory) memory[pointer] = 0 - memory[pointer] = memory[pointer] + 1 - else if (command == '-') do - if (pointer not in memory) memory[pointer] = 0 - memory[pointer] = memory[pointer] - 1 - else if (command == '.') term.log((memory.get(pointer, 0))) - else if (command == ',') memory[pointer] = ord(input()) - else if (command == '[') do - if (memory.get(pointer, 0) == 0) do - loop_depth = 1 - while (loop_depth > 0) do - code_ptr = code_ptr + 1 - if (code[code_ptr] == '[') loop_depth = loop_depth + 1 - else if (code[code_ptr] == ']') loop_depth = loop_depth - 1 - else loops.append(code_ptr) - else if (command == ']') do - if (memory.get(pointer, 0) != 0) code_ptr = loops[-1] - else loops.pop() - code_ptr = code_ptr + 1 - -interpret('>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-]<.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+.>++++++++++.') \ No newline at end of file +term.time("brainfuck") +term.plain.oneLine(brainfuck(input())) +term.timeEnd("brainfuck") \ No newline at end of file