diff options
Diffstat (limited to 'pkg/pointer/exec.go')
-rw-r--r-- | pkg/pointer/exec.go | 152 |
1 files changed, 144 insertions, 8 deletions
diff --git a/pkg/pointer/exec.go b/pkg/pointer/exec.go index 9d55136..f7fcf8f 100644 --- a/pkg/pointer/exec.go +++ b/pkg/pointer/exec.go @@ -8,32 +8,168 @@ import ( func (p *Pointer) Exec(f *field.Field) (done bool, returnValue *int) { c := p.Get(*f) - for jumpingMode := false; jumpingMode || c == ' ' || c == ';'; c = p.StepAndGet(*f) { - if jumpingMode { + if p.stringMode { + if p.lastCharWasSpace { + for c == ' ' { + c = p.StepAndGet(*f) + } + p.lastCharWasSpace = false + } + if c == '"' { + p.stringMode = false + p.lastCharWasSpace = false + } else { + if c == ' ' { + p.lastCharWasSpace = true + } + p.ss.head.Push(c) + } + } else { + for jumpingMode := false; jumpingMode || c == ' ' || c == ';'; c = p.StepAndGet(*f) { if c == ';' { - jumpingMode = false + jumpingMode = !jumpingMode } - continue } + done, returnValue = p.eval(c, f) } + p.Step(*f) + return +} + +func (p *Pointer) eval(c int, f *field.Field) (done bool, returnValue *int) { + handled := true switch c { case '@': return true, nil case '#': p.Step(*f) case 'j': - n := p.Ss.Pop() + n := p.ss.head.Pop() for j := 0; j < n; j++ { p.Step(*f) } case 'q': - v := p.Ss.Pop() + v := p.ss.head.Pop() return true, &v + case 'k': + n := p.ss.head.Pop() + c = p.StepAndGet(*f) + for jumpingMode := false; jumpingMode || c == ' ' || c == ';'; c = p.StepAndGet(*f) { + if c == ';' { + jumpingMode = !jumpingMode + } + } + for j := 0; j < n; j++ { + p.eval(c, f) + } + case '!': + v := p.ss.head.Pop() + if v == 0 { + v = 1 + } else { + v = 0 + } + p.ss.head.Push(v) + case '`': + b, a := p.ss.head.Pop(), p.ss.head.Pop() + if a > b { + a = 1 + } else { + a = 0 + } + p.ss.head.Push(a) + case '_': + v := p.ss.head.Pop() + if v == 0 { + p.Redirect('>') + } else { + p.Redirect('<') + } + case '|': + v := p.ss.head.Pop() + if v == 0 { + p.Redirect('v') + } else { + p.Redirect('^') + } + case 'w': + b, a := p.ss.head.Pop(), p.ss.head.Pop() + if a < b { + p.Redirect('[') + } else if a > b { + p.Redirect(']') + } + case '+': + b, a := p.ss.head.Pop(), p.ss.head.Pop() + p.ss.head.Push(a + b) + case '*': + b, a := p.ss.head.Pop(), p.ss.head.Pop() + p.ss.head.Push(a * b) + case '-': + b, a := p.ss.head.Pop(), p.ss.head.Pop() + p.ss.head.Push(a - b) + case '/': + b, a := p.ss.head.Pop(), p.ss.head.Pop() + if b == 0 { + p.ss.head.Push(0) + return + } + p.ss.head.Push(a / b) + case '%': + b, a := p.ss.head.Pop(), p.ss.head.Pop() + if b == 0 { + p.ss.head.Push(0) + return + } + p.ss.head.Push(a % b) + case '"': + p.stringMode = true + case '\'': + p.ss.head.Push(p.StepAndGet(*f)) + case 's': + p.Step(*f) + f.Set(p.x, p.y, p.ss.head.Pop()) + case '$': + p.ss.head.Pop() + case ':': + p.ss.head.Duplicate() + case '\\': + p.ss.head.Swap() + case 'n': + p.ss.head.Clear() + case '{': + p.ss.Begin(p) + case '}': + p.ss.End(p) + case 'u': + p.ss.Under() + case 'g': + y, x := p.ss.head.Pop(), p.ss.head.Pop() + p.ss.head.Push(f.Get(x+p.sox, y+p.soy)) + case 'p': + y, x, v := p.ss.head.Pop(), p.ss.head.Pop(), p.ss.head.Pop() + f.Set(x+p.sox, y+p.soy, v) + case '.': + p.DecimalOutput(p.ss.head.Pop()) + case ',': + p.CharacterOutput(p.ss.head.Pop()) + case '&': + p.ss.head.Push(p.DecimalInput()) + case '~': + p.ss.head.Push(p.CharacterInput()) default: - if !p.Redirect(c) { + handled = false + } + if !handled { + switch { + case p.Redirect(c): + case c >= '0' && c <= '9': + p.ss.head.Push(c - '0') + case c >= 'a' && c <= 'f': + p.ss.head.Push(c - 'a' + 10) + default: log.Fatalf("Non implemented instruction code %d : %c", c, c) } } - p.Step(*f) return } |