2022-12-07 15:33:29 +00:00
|
|
|
package com.htmlism.firepower.demo
|
|
|
|
|
2022-12-07 22:49:56 +00:00
|
|
|
import scala.annotation.tailrec
|
|
|
|
import scala.collection.immutable.ListMap
|
2022-12-07 19:42:03 +00:00
|
|
|
import scala.util.chaining.*
|
2022-12-07 15:33:29 +00:00
|
|
|
|
2022-12-07 22:55:54 +00:00
|
|
|
import cats.syntax.all._
|
|
|
|
|
2022-12-07 19:42:03 +00:00
|
|
|
import com.htmlism.firepower.core.AsmBlock.Intent
|
|
|
|
import com.htmlism.firepower.core.*
|
2022-12-07 15:33:29 +00:00
|
|
|
|
|
|
|
object SnakeEasy6502:
|
2022-12-07 23:12:49 +00:00
|
|
|
val program: List[MetaIntent] =
|
2022-12-07 19:42:03 +00:00
|
|
|
List(
|
|
|
|
init.call,
|
|
|
|
loop.call
|
|
|
|
)
|
|
|
|
|
|
|
|
lazy val init =
|
2022-12-07 22:55:54 +00:00
|
|
|
Subroutine("init", "initializes values")
|
2022-12-07 22:49:56 +00:00
|
|
|
.copy(intents =
|
2022-12-07 23:08:09 +00:00
|
|
|
() =>
|
|
|
|
List(
|
|
|
|
initSnake.call
|
|
|
|
)
|
2022-12-07 22:49:56 +00:00
|
|
|
)
|
2022-12-07 19:42:03 +00:00
|
|
|
|
|
|
|
lazy val loop =
|
2022-12-07 22:55:54 +00:00
|
|
|
Subroutine("loop", "primary game loop")
|
2022-12-07 19:42:03 +00:00
|
|
|
|
|
|
|
lazy val initSnake =
|
2022-12-07 22:55:54 +00:00
|
|
|
Subroutine("initSnake", "initializes the snake")
|
2022-12-07 19:42:03 +00:00
|
|
|
|
2022-12-07 23:12:49 +00:00
|
|
|
def firstCodeBlock(xs: List[MetaIntent]): AsmBlock.AnonymousCodeBlock =
|
2022-12-07 19:42:03 +00:00
|
|
|
AsmBlock
|
2022-12-07 23:12:49 +00:00
|
|
|
.AnonymousCodeBlock(xs.map(_.toIntent))
|
2022-12-07 19:42:03 +00:00
|
|
|
|
2022-12-07 23:12:49 +00:00
|
|
|
def callGraph(xs: List[MetaIntent]): List[AsmBlock.NamedCodeBlock] =
|
2022-12-07 22:49:56 +00:00
|
|
|
callGraphRecur(ListMap.empty, xs)
|
|
|
|
.values
|
|
|
|
.toList
|
|
|
|
|
|
|
|
@tailrec
|
|
|
|
private def callGraphRecur(
|
|
|
|
callGraph: ListMap[String, AsmBlock.NamedCodeBlock],
|
2022-12-07 23:12:49 +00:00
|
|
|
todo: List[MetaIntent]
|
2022-12-07 22:49:56 +00:00
|
|
|
): ListMap[String, AsmBlock.NamedCodeBlock] =
|
2022-12-07 23:12:49 +00:00
|
|
|
todo.collect { case x: MetaIntent.Jump => x } match
|
2022-12-07 22:49:56 +00:00
|
|
|
case head :: tail =>
|
|
|
|
if (callGraph.contains(head.target)) callGraphRecur(callGraph, tail)
|
|
|
|
else
|
|
|
|
val sub =
|
|
|
|
AsmBlock.NamedCodeBlock(
|
|
|
|
head.target,
|
2022-12-07 22:55:54 +00:00
|
|
|
head.description.some,
|
2022-12-07 22:49:56 +00:00
|
|
|
List(
|
|
|
|
AsmBlock.Intent(
|
|
|
|
None,
|
|
|
|
List(
|
|
|
|
AsmBlock.Intent.Instruction.zero("rts")
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2022-12-07 23:08:09 +00:00
|
|
|
callGraphRecur(callGraph.updated(head.target, sub), todo ::: head.xs)
|
2022-12-07 22:49:56 +00:00
|
|
|
|
|
|
|
case Nil =>
|
|
|
|
callGraph
|
2022-12-07 19:42:03 +00:00
|
|
|
|
2022-12-07 18:36:57 +00:00
|
|
|
def assemble(opts: AssemblerOptions): List[String] =
|
2022-12-07 19:42:03 +00:00
|
|
|
(firstCodeBlock(program) :: callGraph(program))
|
2022-12-07 15:33:29 +00:00
|
|
|
.map(AsmBlock.toLines(opts.instructionCase))
|
|
|
|
.pipe(xs => AsmBlock.interFlatMap(xs)(List("", ""), identity))
|