Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "errors"
- "fmt"
- "io"
- "os"
- )
- // Instruction action type
- type Action uint8
- // One giant leap backwards for programmer kind
- const (
- // +
- CellInc Action = iota
- // -
- CellDec
- // >
- PtrInc
- // <
- PtrDec
- // ,
- Read
- // .
- Write
- // [
- LStart
- // ]
- LEnd
- None
- )
- // Instruction type
- type Token struct {
- action Action
- value uint
- }
- func newToken(char rune, value uint) Token {
- switch char {
- case '+':
- return Token{CellInc, value}
- case '-':
- return Token{CellDec, value}
- case '>':
- return Token{PtrInc, value}
- case '<':
- return Token{PtrDec, value}
- case ',':
- return Token{Read, 0}
- case '.':
- return Token{Write, 0}
- case '[':
- return Token{LStart, value}
- case ']':
- return Token{LEnd, value}
- default:
- return Token{None, 0}
- }
- }
- func compile(source string) ([]Token, error) {
- tokens := make([]Token, 0, 256)
- loops := make([]int, 0, 64)
- var current rune = 0
- var amount uint = 0
- for _, char := range source {
- switch char {
- case '+', '-', '>', '<':
- if current != 0 {
- if current == char {
- amount++
- } else {
- tokens = append(tokens, newToken(current, amount))
- current, amount = char, 1
- }
- } else {
- current, amount = char, 1
- }
- case ',', '.', '[', ']':
- if current != 0 {
- tokens = append(tokens, newToken(current, amount))
- current, amount = 0, 0
- }
- if char == '[' {
- loops = append(loops, len(tokens))
- tokens = append(tokens, Token{None, 0})
- } else if char == ']' {
- if len(loops) == 0 {
- return nil, errors.New("unmatched ']' character")
- }
- start := loops[len(loops)-1]
- loops = loops[:len(loops)-1]
- tokens[start] = newToken('[', uint(len(tokens)))
- tokens = append(tokens, newToken(']', uint(start)))
- } else {
- tokens = append(tokens, newToken(char, 0))
- }
- }
- }
- if current != 0 {
- tokens = append(tokens, newToken(current, amount))
- }
- if len(loops) != 0 {
- return nil, errors.New("unmatched '[' character")
- }
- return tokens, nil
- }
- func run(tokens []Token) uint64 {
- var array [65536]uint8
- var ptr uint16 = 0
- var cycles uint64 = 0
- i := 0
- for i < len(tokens) {
- token := tokens[i]
- switch token.action {
- case CellInc:
- array[ptr] += uint8(token.value % 256)
- case CellDec:
- array[ptr] -= uint8(token.value % 256)
- case PtrInc:
- ptr += uint16(token.value % 65536)
- case PtrDec:
- ptr -= uint16(token.value % 65536)
- case Read:
- var buffer [1]byte
- for {
- _, err := os.Stdin.Read(buffer[:])
- if err != nil {
- if err == io.EOF {
- array[ptr] = 0
- break
- } else {
- panic(err)
- }
- } else if buffer[0] != 13 {
- array[ptr] = buffer[0]
- break
- }
- }
- case Write:
- _, err := os.Stdout.Write(array[ptr : ptr+1])
- if err != nil {
- panic(err)
- }
- case LStart:
- if array[ptr] == 0 {
- i = int(token.value)
- }
- case LEnd:
- if array[ptr] != 0 {
- i = int(token.value)
- }
- }
- i++
- cycles++
- }
- return cycles
- }
- func main() {
- // Hello World!
- source := "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."
- tokens, err := compile(source)
- if err != nil {
- fmt.Printf("ERROR: %s", err)
- return
- }
- fmt.Printf("\ninstructions: %d\n", run(tokens))
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement