1
0
Fork 0
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:
Knut Ahlers 2019-12-15 16:22:24 +01:00
parent 46cb255359
commit a87fb7eaf6
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E

View file

@ -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