From da7e7dae2b690308fb7ff3aba34145233c740bce Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Fri, 24 Sep 2021 01:26:49 +0200 Subject: Made the interpreter pass most of the mycology test suite --- pkg/pointer/exec.go | 161 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 154 insertions(+), 7 deletions(-) (limited to 'pkg/pointer/exec.go') diff --git a/pkg/pointer/exec.go b/pkg/pointer/exec.go index f7fcf8f..448e1e1 100644 --- a/pkg/pointer/exec.go +++ b/pkg/pointer/exec.go @@ -2,6 +2,9 @@ package pointer import ( "log" + "os" + "time" + "unsafe" "git.adyxax.org/adyxax/gofunge/pkg/field" ) @@ -41,12 +44,21 @@ func (p *Pointer) eval(c int, f *field.Field) (done bool, returnValue *int) { switch c { case '@': return true, nil + case 'z': case '#': p.Step(*f) case 'j': n := p.ss.head.Pop() - for j := 0; j < n; j++ { - p.Step(*f) + if n > 0 { + for j := 0; j < n; j++ { + p.Step(*f) + } + } else { + p.Reverse() + for j := 0; j < -n; j++ { + p.Step(*f) + } + p.Reverse() } case 'q': v := p.ss.head.Pop() @@ -54,13 +66,27 @@ func (p *Pointer) eval(c int, f *field.Field) (done bool, returnValue *int) { case 'k': n := p.ss.head.Pop() c = p.StepAndGet(*f) + steps := 1 for jumpingMode := false; jumpingMode || c == ' ' || c == ';'; c = p.StepAndGet(*f) { + steps += 1 if c == ';' { jumpingMode = !jumpingMode } } - for j := 0; j < n; j++ { - p.eval(c, f) + if n > 0 { + // we need to reverse that step + p.Reverse() + for i := 0; i < steps; i++ { + p.Step(*f) + } + p.Reverse() + if c != ' ' && c != ';' { + if n > 0 { + for i := 0; i < n; i++ { + p.eval(c, f) + } + } + } } case '!': v := p.ss.head.Pop() @@ -140,9 +166,13 @@ func (p *Pointer) eval(c int, f *field.Field) (done bool, returnValue *int) { case '{': p.ss.Begin(p) case '}': - p.ss.End(p) + if p.ss.End(p) { + p.Reverse() + } case 'u': - p.ss.Under() + if p.ss.Under() { + p.Reverse() + } case 'g': y, x := p.ss.head.Pop(), p.ss.head.Pop() p.ss.head.Push(f.Get(x+p.sox, y+p.soy)) @@ -157,6 +187,123 @@ func (p *Pointer) eval(c int, f *field.Field) (done bool, returnValue *int) { p.ss.head.Push(p.DecimalInput()) case '~': p.ss.head.Push(p.CharacterInput()) + case 'y': + n := p.ss.head.Pop() + if n > 22+p.ss.height { + n = n - 20 + if p.ss.head.height <= n { + p.ss.head.Push(0) + } else { + p.ss.head.Push(p.ss.head.data[p.ss.head.height-n]) + } + return + } + now := time.Now() + x, y, lx, ly := f.Dump() + const uintSize = 32 << (^uint(0) >> 32 & 1) // 32 or 64 + heights := make([]int, p.ss.height) + s := p.ss.head + for i := p.ss.height - 1; i >= 0; i-- { + heights[i] = s.height + s = s.next + } + if n <= 0 { + for _, e := range os.Environ() { + p.ss.head.Push(0) + for i := len(e) - 1; i >= 0; i-- { + p.ss.head.Push(int(e[i])) + } + } + } + if n <= 0 { + p.ss.head.Push(0) + p.ss.head.Push(0) + for i := len(p.Argv) - 1; i >= 0; i-- { + p.ss.head.Push(0) + for j := len(p.Argv[i]) - 1; j >= 0; j-- { + p.ss.head.Push(int(p.Argv[i][j])) + } + } + } + if (n > 22 && n <= 22+p.ss.height) || n <= 0 { + for i := 0; i < len(heights); i++ { + p.ss.head.Push(heights[i]) + } + } + if n == 22 || n <= 0 { + p.ss.head.Push(p.ss.height) + } + if n == 21 || n <= 0 { + p.ss.head.Push((now.Hour() * 256 * 256) + (now.Minute() * 256) + now.Second()) + } + if n == 20 || n <= 0 { + p.ss.head.Push(((now.Year() - 1900) * 256 * 256) + (int(now.Month()) * 256) + now.Day()) + } + if n == 19 || n <= 0 { + p.ss.head.Push(lx + x) + } + if n == 18 || n <= 0 { + p.ss.head.Push(ly + y) + } + if n == 17 || n <= 0 { + p.ss.head.Push(x) + } + if n == 16 || n <= 0 { + p.ss.head.Push(y) + } + if n == 15 || n <= 0 { + p.ss.head.Push(p.sox) + } + if n == 14 || n <= 0 { + p.ss.head.Push(p.soy) + } + if n == 13 || n <= 0 { + p.ss.head.Push(p.dx) + } + if n == 12 || n <= 0 { + p.ss.head.Push(p.dy) + } + if n == 11 || n <= 0 { + p.ss.head.Push(p.x) + } + if n == 10 || n <= 0 { + p.ss.head.Push(p.y) + } + if n == 9 || n <= 0 { + p.ss.head.Push(0) + } + if n == 8 || n <= 0 { + p.ss.head.Push(*((*int)(unsafe.Pointer(p)))) + } + if n == 7 || n <= 0 { + p.ss.head.Push(2) + } + if n == 6 || n <= 0 { + p.ss.head.Push('/') + } + if n == 5 || n <= 0 { + p.ss.head.Push(0) // TODO update when implementing = + } + if n == 4 || n <= 0 { + p.ss.head.Push(1) + } + if n == 3 || n <= 0 { + p.ss.head.Push(1048576) + } + if n == 2 || n <= 0 { + p.ss.head.Push(uintSize / 8) + } + if n == 1 || n <= 0 { + p.ss.head.Push(0b00000) // TODO update when implementing t, i, o and = + } + case 'i': + log.Fatalf("Non implemented instruction code %d : %c", c, c) + case 'o': + log.Fatalf("Non implemented instruction code %d : %c", c, c) + case '=': + log.Fatalf("Non implemented instruction code %d : %c", c, c) + case 't': + log.Fatalf("Non implemented instruction code %d : %c", c, c) default: handled = false } @@ -168,7 +315,7 @@ func (p *Pointer) eval(c int, f *field.Field) (done bool, returnValue *int) { case c >= 'a' && c <= 'f': p.ss.head.Push(c - 'a' + 10) default: - log.Fatalf("Non implemented instruction code %d : %c", c, c) + p.Redirect('r') } } return -- cgit v1.2.3