Skip to content

Commit

Permalink
Adding new OpDuplicate
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanmorgan committed Jun 1, 2024
1 parent 20de37f commit 6dd617d
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 31 deletions.
7 changes: 7 additions & 0 deletions parser/execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ func Execute[T Number](data []T, program []Instruction, reader io.ByteReader, wr
data[destPtr] += data[dataPtr] * T(factor)
data[dataPtr] = 0
pc++
case opDupVal:
firstPtr := (operand + dataPtr) & DataMask
secondPtr := (program[pc+1].operand + dataPtr) & DataMask
data[firstPtr] += data[dataPtr]
data[secondPtr] += data[dataPtr]
data[dataPtr] = 0
pc++
case opNoop:
continue
default:
Expand Down
5 changes: 4 additions & 1 deletion parser/execute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ func TestExecuteSmall(t *testing.T) {
{opAddDp, 2},
{opMulVal, -1},
{opNoop, 2},
{opAddDp, -1},
{opDupVal, -1},
{opNoop, -2},
}
startdata := make([]int, 65536)
outputBuf := bufio.NewWriter(&bufferWriter{})
inputBuf := bufio.NewReader(strings.NewReader("no input."))
data := Execute(startdata, program, inputBuf, outputBuf)[:10]
want := []int{0, 0, 0, 0, 0, 0, 10, 0, 0, 0}
want := []int{0, 0, 0, 0, 10, 10, 0, 0, 0, 0}

if !reflect.DeepEqual(data, want) {
t.Errorf("got %v want %v", data, want)
Expand Down
1 change: 1 addition & 0 deletions parser/instruction.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const (
opMove
opSkip
opMulVal
opDupVal
)

var instMap = map[byte]Instruction{
Expand Down
2 changes: 2 additions & 0 deletions parser/instruction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var opName = map[Opcode]string{
opMove: "mov",
opSkip: "skp",
opMulVal: "mul",
opDupVal: "dup",
}

func (inst Instruction) String() string {
Expand Down Expand Up @@ -95,6 +96,7 @@ func TestSameOp(t *testing.T) {
opMove,
opSkip,
opMulVal,
opDupVal,
}

for row, rval := range opsList {
Expand Down
9 changes: 5 additions & 4 deletions parser/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ func instPrint(inst, lastInst Instruction) string {
return "[" + repeatDirection("<", ">", inst.operand) + "]"
case opMulVal:
return ""
case opDupVal:
return ""
case opNoop:
if lastInst.operator == opMulVal {
multiplier := strings.Repeat("+", abs(inst.operand))
if inst.operand < 0 {
multiplier = strings.Repeat("-", abs(inst.operand))
}
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) + "]"
}
return ""
default:
Expand Down
6 changes: 5 additions & 1 deletion parser/print_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ func TestPrint(t *testing.T) {
{opMove, 2},
{opJmpZ, 7},
{opIn, 1},
{opMulVal, 2},
{opNoop, 2},
{opDupVal, 1},
{opNoop, 2},
{opJmpNz, 5},
{opAddDp, 2},
}
var buf bytes.Buffer
outputBuf := bufio.NewWriter(&buf)
Print(program, outputBuf)
got := buf.String()
want := " \n >>>>>\n [-]\n +++++\n [->>+<<]\n [\n\t ,\n ]\n >>\n"
want := " \n >>>>>\n [-]\n +++++\n [->>+<<]\n [\n\t ,\n\t [->>++<<]\n\t \n\t [->+>+<<]\n ]\n >>\n"

if !reflect.DeepEqual(got, want) {
t.Errorf("got %v want %v", got, want)
Expand Down
58 changes: 38 additions & 20 deletions parser/tokenise.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,32 +73,27 @@ func Tokenise(input io.ByteReader) (program []Instruction, err error) {
program = program[:pc]
program = append(program, Instruction{opSkip, offset})
case pc-jmpPc == 5: // looking for opMulVal and opMove
var factor, offset = 0, 0
if program[pc-4].Complement(NewInstruction('+')) &&
program[pc-3].Complement(program[pc-1]) &&
program[pc-2].SameOp(NewInstruction('+')) { // open with minus
pointers, factors, ok := evalFactors(program[jmpPc+1 : pc])

factor = program[pc-2].operand
offset = program[pc-3].operand

} else if program[pc-1].Complement(NewInstruction('+')) &&
program[pc-4].Complement(program[pc-2]) &&
program[pc-3].SameOp(NewInstruction('+')) { // close with minus

factor = program[pc-3].operand
offset = program[pc-4].operand

}
if factor == 1 {
if ok && factors[0] == 1 {
pc = jmpPc
program = program[:pc]
program = append(program, Instruction{opMove, offset})
} else if factor != 0 {
program = append(program, Instruction{opMove, pointers[0]})
} else if ok && factors[0] != 0 {
pc = jmpPc
program = program[:pc]
program = append(program, Instruction{opMulVal, pointers[0]})
pc++
program = append(program, Instruction{opNoop, factors[0]})
}
case pc-jmpPc == 7: //looking for opDupVal
pointers, factors, ok := evalFactors(program[jmpPc+1 : pc])
if ok && factors[0] == 1 && factors[1] == 1 {
pc = jmpPc
program = program[:pc]
program = append(program, Instruction{opMulVal, offset})
program = append(program, Instruction{opDupVal, pointers[0]})
pc++
program = append(program, Instruction{opNoop, factor})
program = append(program, Instruction{opNoop, pointers[1]})
}
}
}
Expand All @@ -109,3 +104,26 @@ func Tokenise(input io.ByteReader) (program []Instruction, err error) {
}
return
}

func evalFactors(program []Instruction) (pointers, factors []int, ok bool) {
ok = false
collect := 0
pointers = make([]int, 0)
factors = make([]int, 0)
for _, inst := range program {
if inst.SameOp(NewInstruction('>')) {
collect += inst.operand
} else if collect == 0 && inst.Complement(NewInstruction('+')) {
ok = true
} else if inst.SameOp(NewInstruction('-')) {
pointers = append(pointers, collect)
factors = append(factors, inst.operand)
} else {
return pointers, factors, false
}
}
if collect != 0 || !ok {
return pointers, factors, false
}
return
}
20 changes: 15 additions & 5 deletions parser/tokenise_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,25 @@ func TestTokenise(t *testing.T) {
},
},
{
"op_jmp_z_nz",
"op_dup",
">[->>+>+<<<]",
[]Instruction{
{opNoop, 0},
{opAddDp, 1},
{opDupVal, 2},
{opNoop, 3},
},
},
{
"op_jmp_z_nz",
">[->>,>+<<<]",
[]Instruction{
{opNoop, 0},
{opAddDp, 1},
{opJmpZ, 9},
{opAddVal, -1},
{opAddDp, 2},
{opAddVal, 1},
{opIn, 1},
{opAddDp, 1},
{opAddVal, 1},
{opAddDp, -3},
Expand All @@ -113,10 +123,10 @@ func TestTokenise(t *testing.T) {
got, err := Tokenise(bufio.NewReader(strings.NewReader(v.code)))
want := v.program

if !reflect.DeepEqual(got, want) {
t.Errorf("got %v want %v", got, want)
} else if err != nil {
if err != nil {
t.Errorf("Error thrown %v", err)
} else if !reflect.DeepEqual(got, want) {
t.Errorf("got %v want %v", got, want)
}
})
}
Expand Down

0 comments on commit 6dd617d

Please sign in to comment.