hardcode registers to improve type inference opportunities

This commit is contained in:
Mark Canlas 2022-11-20 01:59:32 -05:00
parent 627bfcbeab
commit ca2333ccc5
8 changed files with 60 additions and 29 deletions

View File

@ -1,7 +1,13 @@
package com.htmlism.scratchpad
object Load:
def const[R: Register, A: Encoded.Byte](x: A): Asm1[R] =
def constA[B: Encoded.Byte](x: B): Asm1[Reg.A] =
Const(x)
def constX[B: Encoded.Byte](x: B): Asm1[Reg.X] =
Const(x)
def constY[B: Encoded.Byte](x: B): Asm1[Reg.Y] =
Const(x)
case class Const[R, A: Encoded.Byte](x: A)(using R: Register[R]) extends Asm1[R]:

View File

@ -2,14 +2,14 @@ package com.htmlism.scratchpad
// https://mads.atari8.info/mads_eng.html#_mv
object Move:
def const[R: Register, A: WriteLease.ByteAddress, X: Encoded.Byte](x: X): Asm2[R, A] =
def constA[A, X: Encoded.Byte](x: X, dest: WriteLease.ByteAddress[A]): Asm2[Reg.A, A] =
Load
.const[R, X](x)
.widenWith[A] andThen Store.from[R, A]
.constA(x)
.widenWith[A] andThen Store.fromA(dest)
def from[R: Register, A: ReadLease.ByteAddress, B: WriteLease.ByteAddress]: Asm3[R, A, B] =
Asm3Instructions(List(""))
object Word:
def const[R: Register, A: WriteLease.WordAddress, X: Encoded.Word](x: X): Asm2[R, A] =
def const[R: Register, A, X: Encoded.Word](x: X, dest: WriteLease.ByteAddress[A]): Asm2[R, A] =
Asm2Instructions(List(""))

View File

@ -1,9 +1,15 @@
package com.htmlism.scratchpad
object Store:
def from[R: Register, A: WriteLease.ByteAddress]: Asm2[R, A] =
Byte[R, A]()
def fromA[B](dest: WriteLease.ByteAddress[B]): Asm2[Reg.A, B] =
Byte[Reg.A, B](dest)
case class Byte[R, A]()(using R: Register[R], A: WriteLease.ByteAddress[A]) extends Asm2[R, A]:
def fromX[B](dest: WriteLease.ByteAddress[B]): Asm2[Reg.X, B] =
Byte[Reg.X, B](dest)
def fromY[B](dest: WriteLease.ByteAddress[B]): Asm2[Reg.Y, B] =
Byte[Reg.Y, B](dest)
case class Byte[R, A](dest: WriteLease.ByteAddress[A])(using R: Register[R]) extends Asm2[R, A]:
def xs: List[String] =
List("ST" + R.name)

View File

@ -1,8 +1,12 @@
package com.htmlism.scratchpad
trait WriteLease[A]
trait WriteLease[A]:
def canon: A
def to(f: A => Int): WriteLease.ByteAddress[A] =
WriteLease.ByteAddress(f(canon))
object WriteLease:
trait ByteAddress[A]
case class ByteAddress[A](address: Int)
trait WordAddress[A]
case class WordAddress[A](address: Int)

View File

@ -1,11 +1,12 @@
package com.htmlism
package object scratchpad:
type A =
Register.A
object Reg:
type A =
Register.A
type X =
Register.X
type X =
Register.X
type Y =
Register.Y
type Y =
Register.Y

View File

@ -6,12 +6,26 @@ object ComplicatedResourceSuite extends FunSuite:
def headAddr: Int =
address
def tailAddres: Int =
def tailAddr: Int =
address + 1
def setHead(x: Int)(using W: WriteLease[A]): Asm1[Register.A] =
Load.Const[Register.A, Int](x)
def setHead(x: Int)(using W: WriteLease[A]): Asm2[Register.A, A] =
Move.constA(x, W.to(_.headAddr))
class PlayerOne extends Player[PlayerOne](40)
object PlayerOne extends PlayerOne:
given write: WriteLease[PlayerOne] with
def canon: PlayerOne =
PlayerOne
class PlayerTwo extends Player[PlayerTwo](80)
object PlayerTwo extends PlayerTwo:
given write: WriteLease[PlayerTwo] with
def canon: PlayerTwo =
PlayerTwo
test("use write lease") {
expect.eql(List("LDA", "STA"), PlayerOne.setHead(0)(using PlayerOne.write).xs)
}

View File

@ -12,23 +12,23 @@ class ExampleRegister
class FeatureSpec extends AnyFunSuite with Matchers:
test("zero page address as write only supports writing") {
ExampleRegister
.writeConst(2)[A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
.writeConst(2)[Reg.A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
}
test("zero page address as read/write supports writing") {
ExampleRegister
.writeConst(2)[A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
.writeConst(2)[Reg.A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
}
test("writing to an address can use A, X, and Y registers for bouncing") {
ExampleRegister
.writeConst(2)[A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
.writeConst(2)[Reg.A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
ExampleRegister
.writeConst(2)[X] shouldBe "LDX 2 STX 1 ; example = 2, via X"
.writeConst(2)[Reg.X] shouldBe "LDX 2 STX 1 ; example = 2, via X"
ExampleRegister
.writeConst(2)[Y] shouldBe "LDY 2 STY 1 ; example = 2, via Y"
.writeConst(2)[Reg.Y] shouldBe "LDY 2 STY 1 ; example = 2, via Y"
}
ignore("the write payload is a typesafe enum") {}
@ -36,4 +36,4 @@ class FeatureSpec extends AnyFunSuite with Matchers:
// intializations must be constant
// cannot involve reading from a register, that is a side-effect
// can also support 16-bit initializations
ignore("initializations of the same value and register are aggregated") {}
ignore("initializations of the same value and register are aggReg.Ated") {}

View File

@ -7,13 +7,13 @@ object RegisterSuite extends FunSuite:
ev
test("the accumulator is a register") {
expect.eql("A", reg[A].name)
expect.eql("A", reg[Reg.A].name)
}
test("X is a register") {
expect.eql("X", reg[X].name)
expect.eql("X", reg[Reg.X].name)
}
test("Y is a register") {
expect.eql("Y", reg[Y].name)
expect.eql("Y", reg[Reg.Y].name)
}