diff --git a/parser/print.go b/parser/print.go index 1e50604..9e618e2 100644 --- a/parser/print.go +++ b/parser/print.go @@ -3,6 +3,7 @@ package parser import ( "bufio" "fmt" + "iter" "strings" ) @@ -20,68 +21,66 @@ func repeatDirection(neg, pos string, vect int) string { return strings.Repeat(neg, abs(vect)) } -func instPrint(inst, lastInst, lastlastInst Instruction) string { - switch inst.operator { - case opAddDp: - return repeatDirection("<", ">", inst.operand) - case opAddVal: - return repeatDirection("-", "+", inst.operand) - case opSetVal: - prefix := "[-]" - if lastInst.IsZeroOp() && inst.operand != 0 { - prefix = "" - } - return prefix + repeatDirection("-", "+", inst.operand) - case opOut: - return "." - case opIn: - return "," - case opJmpZ: - return "[" - case opJmpNz: - return "]" - case opMove: - return "[-" + repeatDirection("<", ">", inst.operand) + "+" + repeatDirection(">", "<", inst.operand) + "]" - case opMovN: - return "[-" + repeatDirection("<", ">", inst.operand) + "-" + repeatDirection(">", "<", inst.operand) + "]" - case opSkip: - return "[" + repeatDirection("<", ">", inst.operand) + "]" - case opNoop: - if lastInst.operator == opMulVal { - multiplier := repeatDirection("-", "+", inst.operand) - return "[-" + repeatDirection("<", ">", lastInst.operand) + multiplier + repeatDirection(">", "<", lastInst.operand) + "]" - } else if lastInst.operator == opDupVal { - return "[-" + repeatDirection("<", ">", lastInst.operand) + "+" + repeatDirection("<", ">", inst.operand-lastInst.operand) + "+" + repeatDirection(">", "<", inst.operand) + "]" - } else if lastlastInst.operator == opVec { - multiplier := repeatDirection("-", "+", lastInst.operand) - return "[-" + repeatDirection("<", ">", lastlastInst.operand) + multiplier + repeatDirection("<", ">", inst.operand-lastlastInst.operand) + multiplier + repeatDirection(">", "<", inst.operand) + "]" +func instPrints(program []Instruction) iter.Seq[string] { + return func(yield func(string) bool) { + + depth := 0 + indent := "" + for pc, inst := range program { + indent = strings.Repeat("\t", depth) + str := "" + switch inst.operator { + case opAddDp: + str = repeatDirection("<", ">", inst.operand) + case opAddVal: + str = repeatDirection("-", "+", inst.operand) + case opSetVal: + prefix := "[-]" + if program[pc-1].IsZeroOp() && inst.operand != 0 { + prefix = "" + } + str = prefix + repeatDirection("-", "+", inst.operand) + case opOut: + str = "." + case opIn: + str = "," + case opJmpZ: + str = "[" + depth++ + case opJmpNz: + str = "]" + depth-- + indent = strings.Repeat("\t", depth) + case opMove: + str = "[-" + repeatDirection("<", ">", inst.operand) + "+" + repeatDirection(">", "<", inst.operand) + "]" + case opMovN: + str = "[-" + repeatDirection("<", ">", inst.operand) + "-" + repeatDirection(">", "<", inst.operand) + "]" + case opSkip: + str = "[" + repeatDirection("<", ">", inst.operand) + "]" + case opMulVal: + multiplier := repeatDirection("-", "+", program[pc+1].operand) + str = "[-" + repeatDirection("<", ">", inst.operand) + multiplier + repeatDirection(">", "<", inst.operand) + "]" + case opDupVal: + str = "[-" + repeatDirection("<", ">", inst.operand) + "+" + repeatDirection("<", ">", program[pc+1].operand-inst.operand) + "+" + repeatDirection(">", "<", program[pc+1].operand) + "]" + case opVec: + multiplier := repeatDirection("-", "+", program[pc+1].operand) + str = "[-" + repeatDirection("<", ">", inst.operand) + multiplier + repeatDirection("<", ">", program[pc+2].operand-inst.operand) + multiplier + repeatDirection(">", "<", program[pc+2].operand) + "]" + case opNoop: + continue + default: + return + } + if !yield(indent + str) { + return + } } - return "" - default: - return "" } } // Print pretty prints out the parsed program. func Print(program []Instruction, writer *bufio.Writer) { - depth := 0 - startLoop := NewInstruction('[') - endLoop := NewInstruction(']') - lastInst := NewInstruction('!') - lastlastInst := NewInstruction('!') - for _, inst := range program { - if inst.SameOp(endLoop) { - depth-- - } - printout := instPrint(inst, lastInst, lastlastInst) - if printout != "" { - fmt.Fprintln(writer, strings.Repeat("\t", depth), printout) - } - if inst.SameOp(startLoop) { - depth++ - } - lastlastInst = lastInst - lastInst = inst + for printout := range instPrints(program) { + fmt.Fprintln(writer, printout) } writer.Flush() } diff --git a/parser/print_test.go b/parser/print_test.go index 0a875c6..7e33fa0 100644 --- a/parser/print_test.go +++ b/parser/print_test.go @@ -8,23 +8,23 @@ import ( "testing" ) -var testprogram = ` >>>>> - [-]+++++ - [->>+<<] - > - [ - , - [<<<] - ++ - [->>++<<] - >> - [->+>+<<] - > - [->+++>+++<<] - ] - >> - . - [->>-<<] +var testprogram = `>>>>> +[-]+++++ +[->>+<<] +> +[ + , + [<<<] + ++ + [->>++<<] + >> + [->+>+<<] + > + [->+++>+++<<] +] +>> +. +[->>-<<] ` func TestPrint(t *testing.T) {