Advertisement
Guest User

Untitled

a guest
Apr 7th, 2017
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 3.37 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "errors"
  5.     "fmt"
  6.     "io"
  7.     "os"
  8. )
  9.  
  10. // Instruction action type
  11. type Action uint8
  12.  
  13. // One giant leap backwards for programmer kind
  14. const (
  15.     // +
  16.     CellInc Action = iota
  17.     // -
  18.     CellDec
  19.     // >
  20.     PtrInc
  21.     // <
  22.     PtrDec
  23.     // ,
  24.     Read
  25.     // .
  26.     Write
  27.     // [
  28.     LStart
  29.     // ]
  30.     LEnd
  31.     None
  32. )
  33.  
  34. // Instruction type
  35. type Token struct {
  36.     action Action
  37.     value  uint
  38. }
  39.  
  40. func newToken(char rune, value uint) Token {
  41.     switch char {
  42.     case '+':
  43.         return Token{CellInc, value}
  44.     case '-':
  45.         return Token{CellDec, value}
  46.     case '>':
  47.         return Token{PtrInc, value}
  48.     case '<':
  49.         return Token{PtrDec, value}
  50.     case ',':
  51.         return Token{Read, 0}
  52.     case '.':
  53.         return Token{Write, 0}
  54.     case '[':
  55.         return Token{LStart, value}
  56.     case ']':
  57.         return Token{LEnd, value}
  58.     default:
  59.         return Token{None, 0}
  60.     }
  61. }
  62.  
  63. func compile(source string) ([]Token, error) {
  64.     tokens := make([]Token, 0, 256)
  65.     loops := make([]int, 0, 64)
  66.     var current rune = 0
  67.     var amount uint = 0
  68.  
  69.     for _, char := range source {
  70.         switch char {
  71.         case '+', '-', '>', '<':
  72.             if current != 0 {
  73.                 if current == char {
  74.                     amount++
  75.                 } else {
  76.                     tokens = append(tokens, newToken(current, amount))
  77.                     current, amount = char, 1
  78.                 }
  79.             } else {
  80.                 current, amount = char, 1
  81.             }
  82.         case ',', '.', '[', ']':
  83.             if current != 0 {
  84.                 tokens = append(tokens, newToken(current, amount))
  85.                 current, amount = 0, 0
  86.             }
  87.  
  88.             if char == '[' {
  89.                 loops = append(loops, len(tokens))
  90.                 tokens = append(tokens, Token{None, 0})
  91.             } else if char == ']' {
  92.                 if len(loops) == 0 {
  93.                     return nil, errors.New("unmatched ']' character")
  94.                 }
  95.  
  96.                 start := loops[len(loops)-1]
  97.                 loops = loops[:len(loops)-1]
  98.  
  99.                 tokens[start] = newToken('[', uint(len(tokens)))
  100.                 tokens = append(tokens, newToken(']', uint(start)))
  101.             } else {
  102.                 tokens = append(tokens, newToken(char, 0))
  103.             }
  104.         }
  105.     }
  106.  
  107.     if current != 0 {
  108.         tokens = append(tokens, newToken(current, amount))
  109.     }
  110.  
  111.     if len(loops) != 0 {
  112.         return nil, errors.New("unmatched '[' character")
  113.     }
  114.  
  115.     return tokens, nil
  116. }
  117.  
  118. func run(tokens []Token) uint64 {
  119.     var array [65536]uint8
  120.     var ptr uint16 = 0
  121.     var cycles uint64 = 0
  122.     i := 0
  123.  
  124.     for i < len(tokens) {
  125.         token := tokens[i]
  126.  
  127.         switch token.action {
  128.         case CellInc:
  129.             array[ptr] += uint8(token.value % 256)
  130.         case CellDec:
  131.             array[ptr] -= uint8(token.value % 256)
  132.         case PtrInc:
  133.             ptr += uint16(token.value % 65536)
  134.         case PtrDec:
  135.             ptr -= uint16(token.value % 65536)
  136.         case Read:
  137.             var buffer [1]byte
  138.  
  139.             for {
  140.                 _, err := os.Stdin.Read(buffer[:])
  141.                 if err != nil {
  142.                     if err == io.EOF {
  143.                         array[ptr] = 0
  144.                         break
  145.                     } else {
  146.                         panic(err)
  147.                     }
  148.                 } else if buffer[0] != 13 {
  149.                     array[ptr] = buffer[0]
  150.                     break
  151.                 }
  152.             }
  153.         case Write:
  154.             _, err := os.Stdout.Write(array[ptr : ptr+1])
  155.             if err != nil {
  156.                 panic(err)
  157.             }
  158.         case LStart:
  159.             if array[ptr] == 0 {
  160.                 i = int(token.value)
  161.             }
  162.         case LEnd:
  163.             if array[ptr] != 0 {
  164.                 i = int(token.value)
  165.             }
  166.         }
  167.  
  168.         i++
  169.         cycles++
  170.     }
  171.  
  172.     return cycles
  173. }
  174.  
  175. func main() {
  176.     // Hello World!
  177.     source := "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."
  178.  
  179.     tokens, err := compile(source)
  180.     if err != nil {
  181.         fmt.Printf("ERROR: %s", err)
  182.         return
  183.     }
  184.  
  185.     fmt.Printf("\ninstructions: %d\n", run(tokens))
  186. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement