diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fcc5c10 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/cmd/creature/creature diff --git a/cmd/creature/examples/echo b/cmd/creature/examples/echo new file mode 100644 index 0000000..2db9479 --- /dev/null +++ b/cmd/creature/examples/echo @@ -0,0 +1,10 @@ +--- +0 0 +F + +0 1 +F + +0 1 +0 0 +E diff --git a/cmd/creature/main.go b/cmd/creature/main.go new file mode 100644 index 0000000..2b9c1d9 --- /dev/null +++ b/cmd/creature/main.go @@ -0,0 +1,104 @@ +package main + +import "io" +import "os" +import "fmt" +import "bufio" +import "strconv" +import cre "git.tebibyte.media/sashakoshka/creature" + +func main() { + if len(os.Args) != 2 { + logLine("ERR file unspecified") + os.Exit(1) + } + + file, err := os.Open(os.Args[1]) + if err != nil { + logLine("ERR could not open file: " + err.Error()) + os.Exit(1) + } + + program, block, err := readFile(file) + if err != nil { + logLine("ERR could not read file: " + err.Error()) + os.Exit(1) + } + + machine := cre.Machine[int]{} + + machine.LoadProgram(program) + machine.LoadMemory(block) + + machine.Register(0, read) + machine.Register(1, write) + + err = machine.Execute(0) + if err != nil { + logLine("XXX machine failed: " + err.Error()) + os.Exit(1) + } +} + +func read(machine *cre.Machine[int]) (stop bool) { + ch := []byte{0} + os.Stdin.Read(ch) + machine.Push(int(ch[0])) + return +} + +func write(machine *cre.Machine[int]) (stop bool) { + print(string(rune(machine.Pop()))) + return +} + +func logLine (message ...any) { + fmt.Fprintln(os.Stderr, message...) +} + +func readFile (reader io.Reader) (program []int, block []int, err error) { + scanner := bufio.NewScanner(reader) + scanner.Split(bufio.ScanWords) + + blockLen := 0 + block = make([]int, 8) + for scanner.Scan() { + if scanner.Text() == "---" { + break + } + if blockLen >= len(block) { + newSlice := make([]int, len(block) * 2) + copy(newSlice, block) + block = newSlice + } + var number int64 + number, err = strconv.ParseInt(scanner.Text(), 16, 64) + if err != nil { + return + } + block[blockLen] = int(number) + blockLen ++ + } + block = block[:blockLen] + + programLen := 0 + program = make([]int, 8) + for scanner.Scan() { + if programLen >= len(program) { + newSlice := make([]int, len(program) * 2) + copy(newSlice, program) + program = newSlice + } + var number int64 + number, err = strconv.ParseInt(scanner.Text(), 16, 64) + if err != nil { + return + } + program[programLen] = int(number) + programLen ++ + } + program = program[:programLen] + return +} + + diff --git a/cmd/main.go b/cmd/main.go deleted file mode 100644 index 06ab7d0..0000000 --- a/cmd/main.go +++ /dev/null @@ -1 +0,0 @@ -package main