Execute SNUSP/Go

From Rosetta Code
Execute SNUSP/Go is an implementation of SNUSP. Other implementations of SNUSP.
Execute SNUSP/Go is part of RCSNUSP. You may find other members of RCSNUSP at Category:RCSNUSP.

Only Core SNUSP today. Fixed size data store, no bounds checking.

package main

import (
    "fmt"
    "strings"
)

// lovely Core SNUSP implementation of Hello World,
// taken from the Ruby Execute SNUSP page.
// it happens to run with only 5 bytes of data store!
const hw = `
/++++!/===========?\>++.>+.+++++++..+++\
\+++\ | /+>+++++++>/ /++++++++++<<.++>./
$+++/ | \+++++++++>\ \+++++.>.+++.-----\
      \==-<<<<+>+++/ /=.>.+>.--------.-/`

func main() {
    snusp(5, hw)
}

// input is a multi-line string.
func snusp(dLen int, raw string) {
    ds := make([]byte, dLen) // data store
    var dp int               // data pointer

    // toss leading \n of code if it's there
    if raw[0] == '\n' {
        raw = raw[1:]
    }

    // make 2 dimensional instruction store, declare instruction pointers
    is := strings.Split(raw, "\n")
    var ipr, ipc int

    // look for starting instruction
findStart:
    for r, row := range is {
        for c, i := range row {
            if i == '$' {
                ipr, ipc = r, c
                break findStart
            }
        }
    }

    // starting direction is always rt
    const (
        rt = iota
        dn
        lt
        up
    )
    id := rt

    // handy, below
    step := func() {
        if id&1 == 0 {
            ipc += 1 - int(id&2)
        } else {
            ipr += 1 - int(id&2)
        }
    }

    // execute
    for ipr >= 0 && ipr < len(is) && ipc >= 0 && ipc < len(is[ipr]) {
        switch is[ipr][ipc] {
        case '>':
            dp++
        case '<':
            dp--
        case '+':
            ds[dp]++
        case '-':
            ds[dp]--
        case '.':
            fmt.Printf("%c", ds[dp])
        case ',':
            fmt.Scanf("%c", &ds[dp])
        case '/':
            id = ^id
        case '\\':
            id ^= 1
        case '!':
            step()
        case '?':
            if ds[dp] == 0 {
                step()
            }
        }
        step()
    }
}

Output:

Hello World!