Day 23 Complete

This commit is contained in:
2016-12-23 13:20:07 -06:00
parent 99e36b8912
commit 54a91e53c7
3 changed files with 212 additions and 56 deletions

View File

@@ -6,6 +6,7 @@ import (
"strings"
"time"
"github.com/fatih/color"
termbox "github.com/nsf/termbox-go"
"../../"
@@ -18,9 +19,10 @@ var regs = map[string]int{
"d": 0,
}
var instructions []string
var curr int
var pause bool
var instructions, lastInst []string
var curr, cursor int
var pause, step, skip bool
var breakpoints []int
func main() {
var debug bool
@@ -54,70 +56,107 @@ func main() {
var ins []string
for curr < len(instructions) || done {
if debug {
lastInst := ins
// print state and wait for user to step
PrintState()
fmt.Println("Last Instruction:", lastInst)
//PrintInstructionState()
fmt.Println("(q): quit (space): pause/unpause")
ev := <-eventChan
if ev.Type == termbox.EventKey {
if ev.Key == termbox.KeySpace {
pause = !pause
}
if ev.Ch == 'q' {
break
}
}
lastInst = ins
}
ins = strings.Fields(instructions[curr])
curr++
if len(ins) == 0 {
break
}
// Optimize multiplication
/*
// TODO:
> cpy b c
inc a
dec c
jnz c -2
dec d
jnz d -5
== mlt b d a
and curr += 5
== add (b * d) to a
set c & d to 0
curr += 5
*/
if ins[0] == "cpy" {
if strings.HasPrefix(instructions[curr+1], "inc") && strings.HasPrefix(instructions[curr+2], "dec") && strings.HasPrefix(instructions[curr+3], "jnz") && strings.HasPrefix(instructions[curr+4], "dec") && strings.HasPrefix(instructions[curr+5], "jnz") {
allGood := true
// The right instruction set, make sure the arguments match up
if len(instructions) >= curr+6 {
ins1 := strings.Fields(instructions[curr+1])
ins2 := strings.Fields(instructions[curr+2])
ins3 := strings.Fields(instructions[curr+3])
ins4 := strings.Fields(instructions[curr+4])
ins5 := strings.Fields(instructions[curr+5])
// Make sure all "c"s are correct
if ins[2] != ins2[1] && ins[2] != ins3[1] {
allGood = false
}
if allGood {
// Make sure all "b"s are correct
if ins[1] == ins1[1] || ins[1] == ins2[1] || ins[1] == ins4[1] {
allGood = false
if ins1[0] == "inc" && ins2[0] == "dec" && ins3[0] == "jnz" && ins4[0] == "dec" && ins5[0] == "jnz" {
allGood := true
if allGood {
// Do the multiplication
// ins[1] * ins4[1]
// add that value to ins1[1]
// set ins[2] to 0
// set ins4[1] to 0
// Then add 5 to the pc
src1 := ins[1]
src2 := ins4[1]
dst := ins1[1]
if _, ok := regs[dst]; !ok {
// Invalid destination register
allGood = false
}
if _, ok := regs[src1]; !ok {
// Invalid source register
allGood = false
}
if _, ok := regs[src2]; !ok {
allGood = false
}
if allGood {
regs[dst] += (regs[src1] * regs[src2])
curr += 6
skip = true
}
}
}
if allGood {
// Make sure all "d"s are correct
if (ins[1] == ins4[1] || ins[2] == ins4[1]) || ins4[1] != ins5[1] {
allGood = false
}
}
if allGood {
// Go ahead and change the instruction
ins = []string{"mult", ins[1], ins4[1], ins1[1]}
curr += 5
}
}
}
if debug {
if isBreakpoint(curr + 1) {
pause = true
step = false
}
for pause && !step {
// print state and wait for user to step
PrintState()
fmt.Println("Last Instruction:", lastInst)
PrintInstructionState()
fmt.Println("(q): quit (space): pause/unpause (s): step (b): toggle breakpoint")
ev := <-eventChan
if ev.Type == termbox.EventKey {
switch {
case ev.Key == termbox.KeySpace:
pause = !pause
case ev.Ch == 'q':
done = true
case ev.Ch == 'b':
toggleBreakpoint(cursor)
case ev.Ch == 's':
step = true
case ev.Key == termbox.KeyArrowUp:
if cursor > 0 {
cursor--
}
case ev.Key == termbox.KeyArrowDown:
if cursor < len(instructions)-1 {
cursor++
}
}
}
}
step = false
}
if done {
// User hit 'q'
break
}
if skip {
skip = false
continue
}
curr++
switch ins[0] {
case "jnz":
// If we have a jnz c -2 it could be moving all of c into another register
@@ -211,6 +250,8 @@ func main() {
}
}
PrintState()
fmt.Println("Press any key to exit")
termbox.PollEvent()
}
// Fancy State Printing
@@ -229,11 +270,21 @@ func PrintRegs() {
func PrintInstructionState() {
for pi := range instructions {
if pi == curr {
fmt.Print("> ")
fmt.Print(">")
} else {
fmt.Print(" ")
fmt.Print(" ")
}
if isBreakpoint(pi) {
fmt.Print("B")
} else {
fmt.Print(" ")
}
if cursor == pi {
cursor := color.New(color.FgBlack).Add(color.BgWhite)
cursor.Println(instructions[pi])
} else {
fmt.Println(instructions[pi])
}
fmt.Println(instructions[pi])
}
fmt.Println(instructions[curr])
}
@@ -252,3 +303,22 @@ func sendNoneEvent(e chan termbox.Event) {
}
}
}
func toggleBreakpoint(pos int) {
for i := 0; i < len(breakpoints); i++ {
if breakpoints[i] == pos {
breakpoints = append(breakpoints[:i], breakpoints[i+1:]...)
return
}
}
breakpoints = append(breakpoints, pos)
}
func isBreakpoint(pos int) bool {
for i := 0; i < len(breakpoints); i++ {
if breakpoints[i] == pos {
return true
}
}
return false
}