package aoc.y2019.intcode import cats.data.{Kleisli, State} case class OperandMode(get: Kleisli[Operation, BigInt, BigInt], set: Kleisli[Operation, (BigInt, BigInt), Unit]) object OperandMode { val position: OperandMode = OperandMode( Kleisli(Machine.get), Kleisli { case (address, value) => Machine.set(address, value) } ) val immediate: OperandMode = OperandMode( Kleisli(State.pure), Kleisli(_ => throw new IllegalArgumentException("Cannot set in immediate mode!")) ) val relative: OperandMode = OperandMode( Kleisli { address => for { offset <- Machine.getOffset value <- Machine.get(address + offset) } yield value }, Kleisli { case (address, value) => for { offset <- Machine.getOffset set <- Machine.set(address + offset, value) } yield set } ) val defaultOperandModes: Map[Int, OperandMode] = Map( 0 -> position, 1 -> immediate, 2 -> relative, ) }