forked from gnolang/gno
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add p/demo/bf (brainfuck vm) (gnolang#885)
- Loading branch information
Showing
5 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package bf | ||
|
||
import ( | ||
"strings" | ||
) | ||
|
||
const maxlen = 30000 | ||
|
||
func Execute(code string) string { | ||
var ( | ||
memory = make([]byte, maxlen) // memory tape | ||
pointer = 0 // initial memory pointer | ||
buf strings.Builder | ||
) | ||
|
||
// Loop through each character in the code | ||
for i := 0; i < len(code); i++ { | ||
switch code[i] { | ||
case '>': | ||
// Increment memory pointer | ||
pointer++ | ||
if pointer >= maxlen { | ||
pointer = 0 | ||
} | ||
case '<': | ||
// Decrement memory pointer | ||
pointer-- | ||
if pointer < 0 { | ||
pointer = maxlen - 1 | ||
} | ||
case '+': | ||
// Increment the byte at the memory pointer | ||
memory[pointer]++ | ||
case '-': | ||
// Decrement the byte at the memory pointer | ||
memory[pointer]-- | ||
case '.': | ||
// Output the byte at the memory pointer | ||
buf.WriteByte(memory[pointer]) | ||
case ',': | ||
// Input a byte and store it in the memory | ||
panic("unsupported") | ||
// fmt.Scan(&memory[pointer]) | ||
case '[': | ||
// Jump forward past the matching ']' if the byte at the memory pointer is zero | ||
if memory[pointer] == 0 { | ||
braceCount := 1 | ||
for braceCount > 0 { | ||
i++ | ||
if code[i] == '[' { | ||
braceCount++ | ||
} else if code[i] == ']' { | ||
braceCount-- | ||
} | ||
} | ||
} | ||
case ']': | ||
// Jump backward to the matching '[' if the byte at the memory pointer is nonzero | ||
if memory[pointer] != 0 { | ||
braceCount := 1 | ||
for braceCount > 0 { | ||
i-- | ||
if code[i] == ']' { | ||
braceCount++ | ||
} else if code[i] == '[' { | ||
braceCount-- | ||
} | ||
} | ||
i-- // Move back one more to compensate for the upcoming increment in the loop | ||
} | ||
} | ||
} | ||
return buf.String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package bf | ||
|
||
import ( | ||
"bytes" | ||
"testing" | ||
) | ||
|
||
func TestExecuteBrainfuck(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
code string | ||
expected string | ||
}{ | ||
{ | ||
name: "hello", | ||
code: "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.", | ||
expected: "Hello World", | ||
}, | ||
{ | ||
name: "increment", | ||
code: "+++++ +++++ [ > +++++ ++ < - ] > +++++ .", | ||
expected: "K", | ||
}, | ||
// Add more test cases as needed | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
result := Execute(tc.code) | ||
if result != tc.expected { | ||
t.Errorf("Expected output: %s, but got: %s", tc.expected, result) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Package bf implements a minimalist Brainfuck virtual machine in Gno. | ||
// | ||
// Brainfuck is an esoteric programming language known for its simplicity and minimalistic design. | ||
// It operates on an array of memory cells, with a memory pointer that can move left or right. | ||
// The language consists of eight commands: > < + - . , [ ]. | ||
// | ||
// Usage: | ||
// To execute Brainfuck code, use the Execute function and provide the code as a string. | ||
// | ||
// code := "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------." | ||
// output := bf.Execute(code) | ||
// | ||
// Note: | ||
// This implementation is a minimalist version and may not handle all edge cases or advanced features of the Brainfuck language. | ||
// | ||
// Reference: | ||
// For more information on Brainfuck, refer to the Wikipedia page: https://en.wikipedia.org/wiki/Brainfuck | ||
package bf // import "gno.land/p/demo/bf" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module gno.land/p/demo/bf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package bf | ||
|
||
// for `gno run` | ||
func main() { | ||
code := "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------." | ||
// TODO: code = os.Args... | ||
Execute(code) | ||
} |