From e3bc1251e8cb20b30d0c5a27cd1da8f147a82de7 Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Thu, 23 Sep 2021 00:24:53 +0200 Subject: Began coding the interpreter (only manages the minimal example for now!) --- cmd/headless_interpreter/main.go | 42 ++++++++++++++++++++++++++++++++++++++++ pkg/interpreter/interpreter.go | 40 ++++++++++++++++++++++++++++++++++++++ pkg/pointer/pointer.go | 6 ++++++ pkg/pointer/pointer_test.go | 11 +++++++++++ 4 files changed, 99 insertions(+) create mode 100644 cmd/headless_interpreter/main.go create mode 100644 pkg/interpreter/interpreter.go 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) +} -- cgit v1.2.3