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/field/utils.go | 4 ++ pkg/field/utils_test.go | 6 ++ pkg/pointer/exec.go | 161 +++++++++++++++++++++++++++++++++++++++++-- pkg/pointer/intput-output.go | 9 --- pkg/pointer/pointer.go | 2 + pkg/pointer/stack-stack.go | 37 +++++++--- pkg/pointer/stack.go | 3 + 7 files changed, 195 insertions(+), 27 deletions(-) (limited to 'pkg') diff --git a/pkg/field/utils.go b/pkg/field/utils.go index 4c4774c..1bd2b2b 100644 --- a/pkg/field/utils.go +++ b/pkg/field/utils.go @@ -96,3 +96,7 @@ func (f *Field) Set(x, y, v int) { } } } + +func (f Field) Dump() (int, int, int, int) { + return f.x, f.y, f.lx, f.ly +} diff --git a/pkg/field/utils_test.go b/pkg/field/utils_test.go index 9c1f7c7..837f9fb 100644 --- a/pkg/field/utils_test.go +++ b/pkg/field/utils_test.go @@ -329,3 +329,9 @@ func TestGetAndSetOnEmptyLines(t *testing.T) { field.Set(0, -1, 'c') require.Equal(t, &f, field) } + +func TestDump(t *testing.T) { + // nothing to test really + f := Field{} + f.Dump() +} 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 diff --git a/pkg/pointer/intput-output.go b/pkg/pointer/intput-output.go index cc7533e..ac58d44 100644 --- a/pkg/pointer/intput-output.go +++ b/pkg/pointer/intput-output.go @@ -4,8 +4,6 @@ import ( "fmt" "log" "os" - - "github.com/pkg/term" ) var defaultInputLastChar *int = nil @@ -16,13 +14,6 @@ func DefaultCharacterInput() int { defaultInputLastChar = nil return c } - t, err := term.Open("/dev/stdin") - if err != nil { - log.Fatalf("Could not open stdin: %+v", err) - } - defer t.Close() - defer t.Restore() - term.RawMode(t) b := make([]byte, 1) i, err := os.Stdin.Read(b) if err != nil { diff --git a/pkg/pointer/pointer.go b/pkg/pointer/pointer.go index 2eea79d..d9a6b3d 100644 --- a/pkg/pointer/pointer.go +++ b/pkg/pointer/pointer.go @@ -31,6 +31,8 @@ type Pointer struct { DecimalInput InputFunction CharacterOutput OutputFunction DecimalOutput OutputFunction + // command line arguments + Argv []string } func NewPointer() *Pointer { diff --git a/pkg/pointer/stack-stack.go b/pkg/pointer/stack-stack.go index 2f57b05..404542c 100644 --- a/pkg/pointer/stack-stack.go +++ b/pkg/pointer/stack-stack.go @@ -21,18 +21,27 @@ func (ss *StackStack) Begin(p *Pointer) { np = -np } toss := &Stack{ - size: np, - height: np, - data: make([]int, np), - next: soss, + size: np, + data: make([]int, np), + next: soss, } ss.head = toss - max := n - soss.height - if max < 0 { - max = 0 - } - for i := n - 1; i >= max; i-- { - toss.data[i] = soss.data[soss.height-n+i] + if n > 0 { + toss.height = n + elts := soss.height - n + if elts < 0 { + elts = soss.height + } else { + elts = n + } + for i := 1; i <= elts; i++ { + toss.data[toss.height-i] = soss.data[soss.height-i] + } + soss.height -= elts + } else if n < 0 { + for i := 0; i < np; i++ { + soss.Push(0) + } } x, y := p.GetStorageOffset() soss.Push(x) @@ -50,6 +59,12 @@ func (ss *StackStack) End(p *Pointer) (reflect bool) { x := soss.Pop() p.SetStorageOffset(x, y) if n > 0 { + if n > ss.head.height { + for i := n; i > ss.head.height; i-- { + soss.Push(0) + } + n = ss.head.height + } soss.height += n if soss.size < soss.height { soss.data = append(soss.data, make([]int, soss.height-soss.size)...) @@ -58,7 +73,7 @@ func (ss *StackStack) End(p *Pointer) (reflect bool) { for i := n; i > 0; i-- { soss.data[soss.height-i] = ss.head.data[ss.head.height-i] } - } else { + } else if n < 0 { soss.height += n if soss.height < 0 { soss.height = 0 diff --git a/pkg/pointer/stack.go b/pkg/pointer/stack.go index 1832dbb..ba51c7c 100644 --- a/pkg/pointer/stack.go +++ b/pkg/pointer/stack.go @@ -23,6 +23,9 @@ func (s *Stack) Clear() { func (s *Stack) Duplicate() { if s.height > 0 { s.Push(s.data[s.height-1]) + } else { + s.Push(0) + s.Push(0) } } -- cgit v1.2.3