aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/headless_interpreter/main.go42
-rw-r--r--pkg/interpreter/interpreter.go40
-rw-r--r--pkg/pointer/pointer.go6
-rw-r--r--pkg/pointer/pointer_test.go11
4 files changed, 99 insertions, 0 deletions
diff --git a/cmd/headless_interpreter/main.go b/cmd/headless_interpreter/main.go
new file mode 100644
index 0000000..73b71dc
--- /dev/null
+++ b/cmd/headless_interpreter/main.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+
+ "git.adyxax.org/adyxax/gofunge/pkg/field"
+ "git.adyxax.org/adyxax/gofunge/pkg/interpreter"
+ "git.adyxax.org/adyxax/gofunge/pkg/pointer"
+)
+
+func main() {
+ filename := flag.String("f", "", "b98 file to interpret")
+ help := flag.Bool("h", false, "display this help message")
+ flag.Parse()
+
+ if *help {
+ flag.Usage()
+ os.Exit(0)
+ }
+
+ if *filename == "" {
+ fmt.Println("Error : no b98 file to interpret")
+ flag.Usage()
+ os.Exit(1)
+ }
+ file, err := os.Open(*filename)
+ if err != nil {
+ fmt.Printf("Failed to open file %s : %+v", *filename, err)
+ os.Exit(2)
+ }
+ defer file.Close()
+
+ f, err := field.Load(file)
+ if err != nil {
+ fmt.Printf("Failed to load file %s : %+v", *filename, err)
+ os.Exit(3)
+ }
+
+ interpreter.NewInterpreter(f, pointer.NewPointer()).Run()
+}
diff --git a/pkg/interpreter/interpreter.go b/pkg/interpreter/interpreter.go
new file mode 100644
index 0000000..ce2499d
--- /dev/null
+++ b/pkg/interpreter/interpreter.go
@@ -0,0 +1,40 @@
+package interpreter
+
+import (
+ "log"
+
+ "git.adyxax.org/adyxax/gofunge/pkg/field"
+ "git.adyxax.org/adyxax/gofunge/pkg/pointer"
+)
+
+type Interpreter struct {
+ f *field.Field
+ p *pointer.Pointer
+}
+
+func NewInterpreter(f *field.Field, p *pointer.Pointer) *Interpreter {
+ return &Interpreter{f: f, p: p}
+}
+
+func (i *Interpreter) Run() {
+ for i.p != nil {
+ i.Step()
+ }
+}
+
+func (i *Interpreter) Step() {
+ var prev *pointer.Pointer = nil
+ for p := i.p; p != nil; p = p.Next {
+ switch p.Get(*i.f) {
+ case '@':
+ if prev == nil {
+ i.p = p.Next
+ } else {
+ prev.Next = p.Next
+ }
+ break
+ default:
+ log.Fatalf("Non implemented instruction code %d : %c", p.Get(*i.f), p.Get(*i.f))
+ }
+ }
+}
diff --git a/pkg/pointer/pointer.go b/pkg/pointer/pointer.go
index 5847e70..a833f5b 100644
--- a/pkg/pointer/pointer.go
+++ b/pkg/pointer/pointer.go
@@ -12,6 +12,8 @@ type Pointer struct {
// The Storage offset
sox int
soy int
+ // The next element for the multi-"threaded" b98 interpreter
+ Next *Pointer
}
func NewPointer() *Pointer {
@@ -25,3 +27,7 @@ func (p Pointer) Split() *Pointer {
func (p *Pointer) Step(f field.Field) {
p.x, p.y = f.Step(p.x, p.y, p.dx, p.dy)
}
+
+func (p Pointer) Get(f field.Field) int {
+ return f.Get(p.x, p.y)
+}
diff --git a/pkg/pointer/pointer_test.go b/pkg/pointer/pointer_test.go
index 658528d..ccbf486 100644
--- a/pkg/pointer/pointer_test.go
+++ b/pkg/pointer/pointer_test.go
@@ -39,3 +39,14 @@ func TestStep(t *testing.T) { // Step is thoroughly tested in the field package
p.Step(*f)
require.Equal(t, defaultPointer, p)
}
+
+func TestGet(t *testing.T) {
+ // File of one char
+ file, err := os.Open("../field/test_data/minimal.b98")
+ require.NoError(t, err, "Failed to open file")
+ defer file.Close()
+ f, err := field.Load(file)
+ p := NewPointer()
+ v := p.Get(*f)
+ require.Equal(t, int('@'), v)
+}