iterative support for define block

This commit is contained in:
Mark Canlas 2022-12-06 14:58:20 -05:00
parent 899d36f7fe
commit aacc2d3afa
5 changed files with 98 additions and 13 deletions

View File

@ -1,11 +1,29 @@
; define COLOR_Black 0
; define COLOR_White 1
; define COLOR_Red 2
; define COLOR_Cyan 3
; define COLOR_Purple 4
; define COLOR_Green 5
; define COLOR_Blue 6
; define COLOR_Yellow 7
; define COLOR_Orange 8
; define COLOR_Brown 9
; define COLOR_LightRed 10
; define COLOR_DarkGrey 11
; define COLOR_Grey 12
; define COLOR_LightGreen 13
; define COLOR_LightBlue 14
; define COLOR_LightGrey 15
; $0200 = White
LDA #$01
LDA COLOR_White
STA $0200
; $0201 = Green
LDA #$05
LDA COLOR_Green
STA $0201
; $0202 = Orange
LDA #$08
LDA COLOR_Orange
STA $0202

View File

@ -1,6 +1,12 @@
package com.htmlism.firepower.demo
import scala.collection.immutable._
trait Definable[A]:
def table: ListMap[String, String]
extension (x: A) def toComment: String
extension (x: A) def toValue: Int
extension (x: A) def toDefine: String

View File

@ -1,5 +1,8 @@
package com.htmlism.firepower.demo
import scala.collection.immutable._
import scala.util.chaining._
object Easy6502:
enum Color:
case Black, White, Red, Cyan, Purple, Green, Blue, Yellow, Orange, Brown, LightRed, DarkGrey, Grey, LightGreen,
@ -7,6 +10,15 @@ object Easy6502:
object Color:
given Definable[Color] with
def table: ListMap[String, String] =
Color
.values
.iterator
.map { c =>
"COLOR_" + c.toString -> c.ordinal.toString
}
.pipe(ListMap.from)
extension (x: Color)
def toComment: String =
x.toString
@ -14,3 +26,7 @@ object Easy6502:
extension (x: Color)
def toValue: Int =
x.ordinal
extension (x: Color)
def toDefine: String =
"COLOR_" + x.toString

View File

@ -31,7 +31,7 @@ object PrintPrograms extends ZIOAppDefault:
.pipe(Line.mkString),
"annotated-snake.asm" -> AnnotatedSnake.program,
"print-three-upper.asm" -> PrintThree.assemble(
AssemblerOptions(InstructionCase.Uppercase, DefinitionsMode.UseLiterals)
AssemblerOptions(InstructionCase.Uppercase, DefinitionsMode.UseDefinitions)
),
"print-three-lower.asm" -> PrintThree.assemble(
AssemblerOptions(InstructionCase.Lowercase, DefinitionsMode.UseLiterals)

View File

@ -1,5 +1,6 @@
package com.htmlism.firepower.demo
import scala.collection.immutable._
import scala.util.chaining._
import cats.syntax.all._
@ -8,7 +9,11 @@ import com.htmlism.firepower.core.AsmBlock._
import com.htmlism.firepower.core._
object PrintThree:
case class Move[A: Definable](src: A, dest: String)
case class Move[A: Definable](src: A, dest: String):
def defines: Option[ListMap[String, String]] =
implicitly[Definable[A]]
.table
.some
val program: List[Move[Easy6502.Color]] =
List(
@ -17,25 +22,65 @@ object PrintThree:
Move(Easy6502.Color.Orange, "$0202")
)
def assemble(opt: AssemblerOptions): String =
def assemble(opts: AssemblerOptions): String =
(defines(opts) ++ codes(opts))
.map(AsmBlock.toLines)
.pipe(xs => AsmBlock.interFlatMap(xs)(List("", ""), identity))
.pipe(str.Line.mkString)
private def defines(opts: AssemblerOptions) =
opts.definitionsMode match
case AssemblerOptions.DefinitionsMode.UseLiterals =>
Nil
case AssemblerOptions.DefinitionsMode.UseDefinitions =>
program
.flatMap(_.defines.toList)
.distinct
.map { xs =>
xs
.toList
.map { case (k, v) =>
s"define $k $v"
}
.pipe(AsmBlock.CommentBlock(_))
}
case AssemblerOptions.DefinitionsMode.UseDefinitionsWithMath =>
program
.flatMap(_.defines.toList)
.distinct
.map { xs =>
xs
.toList
.map { case (k, v) =>
s"define $k $v"
}
.pipe(AsmBlock.CommentBlock(_))
}
private def codes(opts: AssemblerOptions) =
program
.map { mv =>
val hex =
f"#$$${mv.src.toValue}%02X"
val argument =
opts.definitionsMode match
case AssemblerOptions.DefinitionsMode.UseLiterals =>
f"#$$${mv.src.toValue}%02X"
case AssemblerOptions.DefinitionsMode.UseDefinitions |
AssemblerOptions.DefinitionsMode.UseDefinitionsWithMath =>
mv.src.toDefine
AsmBlock.Intent(
s"${mv.dest} = ${mv.src.toComment}".some,
List(
AsmBlock.Intent.Instruction(instruction("LDA", opt.instructionCase) + " " + hex, None),
AsmBlock.Intent.Instruction(instruction("STA", opt.instructionCase) + " " + mv.dest, None)
AsmBlock.Intent.Instruction(instruction("LDA", opts.instructionCase) + " " + argument, None),
AsmBlock.Intent.Instruction(instruction("STA", opts.instructionCase) + " " + mv.dest, None)
)
)
}
.pipe(AnonymousCodeBlock(_))
.pipe(List(_))
.map(AsmBlock.toLines)
.pipe(xs => AsmBlock.interFlatMap(xs)(List("", ""), identity))
.pipe(str.Line.mkString)
def instruction(s: String, instructionCase: AssemblerOptions.InstructionCase): String =
instructionCase match