Skip to content

Instantly share code, notes, and snippets.

@nuclearace
Last active August 29, 2015 14:21
Show Gist options
  • Save nuclearace/ee68d51c1c0434207d4e to your computer and use it in GitHub Desktop.
Save nuclearace/ee68d51c1c0434207d4e to your computer and use it in GitHub Desktop.
import Foundation
let valids = [">", "<", "+", "-", ".", ",", "[", "]"] as Set<Character>
var ip = 0
var dp = 0
var data = [UInt8](count: 30_000, repeatedValue: 0)
let input = Process.arguments
if input.count != 2 {
fatalError("Need one input file")
}
let infile = String(contentsOfFile: input[1], encoding: NSUTF8StringEncoding, error: nil) ?? ""
var program = ""
// remove invalid chars
for c in infile {
if valids.contains(c) {
program += String(c)
}
}
let numChars = count(program)
if numChars == 0 {
fatalError("Error reading file")
}
func increaseInstructionPointer() {
++ip
}
func executeInstruction(ins:Character) {
switch ins {
case ">":
++dp
increaseInstructionPointer()
case "<":
--dp
increaseInstructionPointer()
case "+":
data[dp] = data[dp] &+ 1
increaseInstructionPointer()
case "-":
data[dp] = data[dp] &- 1
increaseInstructionPointer()
case ".":
// println(data[dp])
print(Character(UnicodeScalar(data[dp])))
increaseInstructionPointer()
case ",":
handleIn()
increaseInstructionPointer()
case "[":
handleOpenBracket()
case "]":
handleClosedBracket()
default:
fatalError("What")
}
}
func handleIn() {
let input = NSFileHandle.fileHandleWithStandardInput()
let bytes = input.availableData.bytes
let buf = unsafeBitCast(UnsafeBufferPointer(start: bytes, count: 1),
UnsafeBufferPointer<UInt8>.self)
data[dp] = buf[0]
}
func handleOpenBracket() {
if data[dp] == 0 {
var i = 1
while i > 0 {
let ins = program[advance(program.startIndex, ++ip)]
if ins == "[" {
++i
} else if ins == "]" {
--i
}
}
} else {
increaseInstructionPointer()
}
}
func handleClosedBracket() {
if data[dp] != 0 {
var i = 1
while i > 0 {
let ins = program[advance(program.startIndex, --ip)]
if ins == "[" {
--i
} else if ins == "]" {
++i
}
}
} else {
increaseInstructionPointer()
}
}
func printState() {
println("Instruction Pointer: \(ip)")
println("Data Pointer \(dp)")
println("Data in Cell: \(data[dp])")
println()
}
func tick() {
let ins = program[advance(program.startIndex, ip)]
if valids.contains(ins) {
//println("Current instruction: \(ins)")
//printState()
executeInstruction(ins)
} else {
increaseInstructionPointer()
}
}
while ip != numChars {
tick()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment