mirror of
https://github.com/Luzifer/aoc2019.git
synced 2024-12-22 14:01:17 +00:00
Allow force-exit program through context
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
46cb255359
commit
a87fb7eaf6
1 changed files with 32 additions and 6 deletions
38
intcode.go
38
intcode.go
|
@ -1,6 +1,7 @@
|
||||||
package aoc2019
|
package aoc2019
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"log"
|
"log"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -91,24 +92,45 @@ func parseIntcode(code string) ([]int64, error) {
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type intcodeParams struct {
|
||||||
|
// Intcode program to execute
|
||||||
|
Code []int64
|
||||||
|
// Context to execute the program in (program might hang on input if context is closed during input directive)
|
||||||
|
Context context.Context
|
||||||
|
// Channel / Callback to query on input directive
|
||||||
|
In interface{}
|
||||||
|
// Channel to use for output directive
|
||||||
|
Out chan int64
|
||||||
|
}
|
||||||
|
|
||||||
func executeIntcode(code []int64, in interface{}, out chan int64) ([]int64, error) {
|
func executeIntcode(code []int64, in interface{}, out chan int64) ([]int64, error) {
|
||||||
|
return executeIntcodeWithParams(intcodeParams{
|
||||||
|
Code: code,
|
||||||
|
Context: context.Background(),
|
||||||
|
In: in,
|
||||||
|
Out: out,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeIntcodeWithParams(params intcodeParams) ([]int64, error) {
|
||||||
var (
|
var (
|
||||||
|
code = params.Code
|
||||||
inCB func() (int64, error)
|
inCB func() (int64, error)
|
||||||
pos int64
|
pos int64
|
||||||
relativeBase int64
|
relativeBase int64
|
||||||
)
|
)
|
||||||
|
|
||||||
if out != nil {
|
if params.Out != nil {
|
||||||
defer close(out)
|
defer close(params.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch in.(type) {
|
switch params.In.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
inCB = func() (int64, error) { return 0, errors.New("No input available") }
|
inCB = func() (int64, error) { return 0, errors.New("No input available") }
|
||||||
case chan int64:
|
case chan int64:
|
||||||
inCB = func() (int64, error) { return <-(in.(chan int64)), nil }
|
inCB = func() (int64, error) { return <-(params.In.(chan int64)), nil }
|
||||||
case func() (int64, error):
|
case func() (int64, error):
|
||||||
inCB = in.(func() (int64, error))
|
inCB = params.In.(func() (int64, error))
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("Unsupported input type")
|
return nil, errors.New("Unsupported input type")
|
||||||
}
|
}
|
||||||
|
@ -169,6 +191,10 @@ func executeIntcode(code []int64, in interface{}, out chan int64) ([]int64, erro
|
||||||
return nil, errors.Errorf("Code position out of bounds: %d (len=%d)", pos, len(code))
|
return nil, errors.Errorf("Code position out of bounds: %d (len=%d)", pos, len(code))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := params.Context.Err(); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "Context closed")
|
||||||
|
}
|
||||||
|
|
||||||
// Position is expected to be an OpCode
|
// Position is expected to be an OpCode
|
||||||
op := parseOpCode(code[pos])
|
op := parseOpCode(code[pos])
|
||||||
|
|
||||||
|
@ -195,7 +221,7 @@ func executeIntcode(code []int64, in interface{}, out chan int64) ([]int64, erro
|
||||||
pos += 2
|
pos += 2
|
||||||
|
|
||||||
case opCodeTypeOutput: // p1 => out
|
case opCodeTypeOutput: // p1 => out
|
||||||
out <- getParamValue(1, op)
|
params.Out <- getParamValue(1, op)
|
||||||
pos += 2
|
pos += 2
|
||||||
|
|
||||||
case opCodeTypeJumpIfTrue: // p1 != 0 => jmp
|
case opCodeTypeJumpIfTrue: // p1 != 0 => jmp
|
||||||
|
|
Loading…
Reference in a new issue