6502-opcodes/src/main/scala/com/htmlism/ShiftExtractor.scala

45 lines
1.1 KiB
Scala
Raw Normal View History

2018-05-05 18:23:21 +00:00
package com.htmlism
2020-08-13 01:18:38 +00:00
import scala.annotation.tailrec
/**
* Given an `Int`, destructure it into smaller `Int`s that use less bits
*/
2022-02-14 23:11:45 +00:00
trait BitExtractor[A]:
2018-05-05 18:23:21 +00:00
self =>
def length: Int
def unapply(n: Int): Option[A]
2020-08-13 01:18:38 +00:00
/**
* A combinator for appending one extractor to another
*/
2018-05-05 18:23:21 +00:00
def >>[B](that: BitExtractor[B]): BitExtractor[(A, B)] =
2022-09-07 15:21:22 +00:00
new BitExtractor[(A, B)]:
2018-05-05 18:23:21 +00:00
def length: Int = self.length + that.length
def unapply(n: Int): Option[(A, B)] =
for {
2022-12-02 01:44:59 +00:00
b <- that.unapply(n)
2018-05-05 18:23:21 +00:00
shifted = n >> that.length
2022-12-02 01:44:59 +00:00
a <- self.unapply(shifted)
2018-05-05 18:23:21 +00:00
} yield (a, b)
2022-02-14 23:11:45 +00:00
object AtomExtractor:
2020-08-13 01:18:38 +00:00
@tailrec
2018-05-05 18:23:21 +00:00
def pow(ex: Int, acc: Int = 1): Int =
2023-10-03 20:15:10 +00:00
if ex == 0 then acc
else pow(ex - 1, acc * 2)
2018-05-05 18:23:21 +00:00
2022-02-14 23:11:45 +00:00
abstract class PrimitiveBitExtractor(val length: Int) extends BitExtractor[Int]:
2020-08-13 01:18:38 +00:00
private lazy val mask =
AtomExtractor.pow(length) - 1
2018-05-05 18:23:21 +00:00
2020-08-13 01:18:38 +00:00
def unapply(n: Int): Option[Int] =
Some(n & mask)
2018-05-05 18:23:21 +00:00
2022-12-02 01:44:59 +00:00
object OneBit extends PrimitiveBitExtractor(1)
object TwoBits extends PrimitiveBitExtractor(2)
2018-09-26 02:57:26 +00:00
object ThreeBits extends PrimitiveBitExtractor(3)