Skip to content

Commit

Permalink
Make opVec and opDup support multi values.
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanmorgan committed Nov 4, 2024
1 parent a3cff3a commit afe9b5d
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 23 deletions.
24 changes: 14 additions & 10 deletions parser/execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,22 +76,26 @@ func Execute[T Number](data []T, program []Instruction, reader io.ByteReader, wr
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]
destPtr := (operand + dataPtr) & DataMask
data[destPtr] += data[dataPtr]
for pc+1 < len(program) && program[pc+1].operator == opNoop {
destPtr = (program[pc+1].operand + dataPtr) & DataMask
data[destPtr] += data[dataPtr]
pc++
}
data[dataPtr] = 0
pc++
case opVec:
factor := program[pc+1].operand
dataVal := data[dataPtr] * T(factor)
firstPtr := (operand + dataPtr) & DataMask
data[firstPtr] += dataVal
secondPtr := (program[pc+2].operand + dataPtr) & DataMask
data[secondPtr] += dataVal
destPtr := (operand + dataPtr) & DataMask
data[destPtr] += dataVal
for pc+2 < len(program) && program[pc+2].operator == opNoop {
destPtr = (program[pc+2].operand + dataPtr) & DataMask
data[destPtr] += dataVal
pc++
}
data[dataPtr] = 0
pc++
pc++
case opNoop:
continue
default:
Expand Down
3 changes: 2 additions & 1 deletion parser/execute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ func TestExecuteSmall(t *testing.T) {
{opVec, 2},
{opNoop, 2},
{opNoop, 3},
{opNoop, 4},
}
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, -100, 20, 20, 0, 0}
want := []int{0, 0, 0, 0, 0, -100, 20, 20, 20, 0}

if !reflect.DeepEqual(data, want) {
t.Errorf("got %v want %v", data, want)
Expand Down
16 changes: 14 additions & 2 deletions parser/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,22 @@ func instPrints(program []Instruction) iter.Seq[string] {
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) + "]"
str = "[-" + repeatDirection("<", ">", inst.operand) + "+"
for pc+1 < len(program) && program[pc+1].operator == opNoop {
str = str + repeatDirection("<", ">", program[pc+1].operand-inst.operand) + "+"
pc++
inst = program[pc]
}
str = str + repeatDirection(">", "<", program[pc].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) + "]"
str = "[-" + repeatDirection("<", ">", inst.operand) + multiplier
for pc+2 < len(program) && program[pc+2].operator == opNoop {
str = str + repeatDirection("<", ">", program[pc+2].operand-inst.operand) + multiplier
pc++
inst = program[pc+1]
}
str = str + repeatDirection(">", "<", program[pc+1].operand) + "]"
case opNoop:
continue
default:
Expand Down
23 changes: 15 additions & 8 deletions parser/tokenise.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,29 @@ func Tokenise(input io.ByteReader) (program []Instruction, err error) {
pc++
program = append(program, Instruction{opNoop, factors[0]})
}
case pc-jmpPc == 7 || pc-jmpPc == 8: //looking for opDupVal
case pc-jmpPc >= 7: //looking for opDupVal
pointers, factors, ok := evalFactors(program[jmpPc+1 : pc])
if ok && factors[0] == 1 && factors[1] == 1 {
for i := range len(factors) {
ok = ok && factors[0] == factors[i]
}
if ok && factors[0] == 1 {
pc = jmpPc
program = program[:pc]
program = append(program, Instruction{opDupVal, pointers[0]})
pc++
program = append(program, Instruction{opNoop, pointers[1]})
} else if ok && factors[0] == factors[1] {
for _, v := range pointers[1:] {
pc++
program = append(program, Instruction{opNoop, v})
}
} else if ok {
pc = jmpPc
program = program[:pc]
program = append(program, Instruction{opVec, pointers[0]})
pc++
program = append(program, Instruction{opNoop, factors[1]})
pc++
program = append(program, Instruction{opNoop, pointers[1]})
program = append(program, Instruction{opNoop, factors[0]})
for _, v := range pointers[1:] {
pc++
program = append(program, Instruction{opNoop, v})
}
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions parser/tokenise_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,23 +84,25 @@ func TestTokenise(t *testing.T) {
},
{
"op_vec",
">[->>+++>>+++<<<<]",
">[->>+++>+++>+++<<<<]",
[]Instruction{
{opNoop, 0},
{opAddDp, 1},
{opVec, 2},
{opNoop, 3},
{opNoop, 3},
{opNoop, 4},
},
},
{
"op_dup",
">[->>+>+<<<]>[>>+<<-<<+>>]",
">[->>+>+>+<<<<]>[>>+<<-<<+>>]",
[]Instruction{
{opNoop, 0},
{opAddDp, 1},
{opDupVal, 2},
{opNoop, 3},
{opNoop, 4},
{opAddDp, 1},
{opDupVal, 2},
{opNoop, -2},
Expand Down

0 comments on commit afe9b5d

Please sign in to comment.