2020-08-15 18:38:08 +00:00
|
|
|
package com.htmlism.mos6502.dsl
|
|
|
|
|
2020-08-21 07:11:27 +00:00
|
|
|
import scala.collection.immutable.ListSet
|
2020-08-15 18:38:08 +00:00
|
|
|
import scala.collection.mutable.ListBuffer
|
|
|
|
|
2023-10-03 20:15:10 +00:00
|
|
|
import cats.syntax.all.*
|
2020-08-26 06:32:27 +00:00
|
|
|
|
2022-02-14 23:11:45 +00:00
|
|
|
case class AsmDocument(xs: List[TopLevelAsmDocumentFragment]):
|
2020-08-16 05:17:39 +00:00
|
|
|
def toAsm: String =
|
|
|
|
xs
|
|
|
|
.map(_.toAsm)
|
|
|
|
.mkString("\n\n")
|
2020-08-15 18:38:08 +00:00
|
|
|
|
2022-02-14 23:11:45 +00:00
|
|
|
class AsmDocumentContext:
|
2020-08-15 18:38:08 +00:00
|
|
|
private val xs: ListBuffer[TopLevelAsmDocumentFragment] =
|
|
|
|
ListBuffer()
|
|
|
|
|
2020-08-21 07:11:27 +00:00
|
|
|
private var jumps: ListSet[Subroutine] =
|
|
|
|
ListSet()
|
|
|
|
|
2020-08-15 18:38:08 +00:00
|
|
|
def push(x: TopLevelAsmDocumentFragment): Unit =
|
|
|
|
xs.append(x)
|
|
|
|
|
2020-08-21 07:11:27 +00:00
|
|
|
def addJumpRegistry(ys: ListSet[Subroutine]): Unit =
|
|
|
|
jumps = jumps ++ ys
|
|
|
|
|
2022-02-14 23:11:45 +00:00
|
|
|
def toDoc: AsmDocument =
|
2020-08-21 07:11:27 +00:00
|
|
|
val asmFragmentsAndSubroutines =
|
2020-08-21 20:43:23 +00:00
|
|
|
xs.toList ::: jumps.toList ++ jumps.flatMap(_.jumpRegistry).toList
|
2020-08-16 16:55:21 +00:00
|
|
|
|
2020-08-21 07:11:27 +00:00
|
|
|
AsmDocument(asmFragmentsAndSubroutines)
|
2020-08-15 18:38:08 +00:00
|
|
|
|
2022-02-14 23:11:45 +00:00
|
|
|
sealed trait TopLevelAsmDocumentFragment:
|
2020-08-16 05:17:39 +00:00
|
|
|
def toAsm: String
|
2020-08-15 18:38:08 +00:00
|
|
|
|
2022-02-14 23:11:45 +00:00
|
|
|
case class AsmFragment(xs: List[Statement]) extends TopLevelAsmDocumentFragment:
|
2020-08-16 05:17:39 +00:00
|
|
|
def toAsm: String =
|
|
|
|
xs.map(_.toAsm).mkString("\n")
|
2020-08-15 18:38:08 +00:00
|
|
|
|
2020-08-21 20:43:23 +00:00
|
|
|
case class Subroutine(name: String, fragment: AsmFragment, jumpRegistry: ListSet[Subroutine])
|
2022-02-14 23:11:45 +00:00
|
|
|
extends TopLevelAsmDocumentFragment:
|
2020-08-16 16:55:21 +00:00
|
|
|
def toAsm: String =
|
|
|
|
name + ":" + "\n" + fragment.toAsm
|
|
|
|
|
2022-02-14 23:11:45 +00:00
|
|
|
case class DefinitionGroup(comment: String, xs: List[Definition[_]]) extends TopLevelAsmDocumentFragment:
|
|
|
|
def toAsm: String =
|
2020-08-26 06:37:12 +00:00
|
|
|
val groupCommentLine =
|
2020-08-16 05:17:39 +00:00
|
|
|
"; " + comment
|
|
|
|
|
|
|
|
val definitionLines =
|
|
|
|
xs
|
2020-08-26 06:37:12 +00:00
|
|
|
.map { d =>
|
2022-02-14 23:11:45 +00:00
|
|
|
d.comment match
|
2020-08-26 06:37:12 +00:00
|
|
|
case Some(c) =>
|
|
|
|
f"define ${d.name}%-20s${d.value} ; $c"
|
2020-08-16 05:17:39 +00:00
|
|
|
|
2020-08-26 06:37:12 +00:00
|
|
|
case None =>
|
|
|
|
f"define ${d.name}%-20s${d.value}"
|
|
|
|
}
|
|
|
|
|
|
|
|
(groupCommentLine :: definitionLines)
|
2020-08-16 05:17:39 +00:00
|
|
|
.mkString("\n")
|
2020-08-15 18:38:08 +00:00
|
|
|
|
2022-02-14 23:11:45 +00:00
|
|
|
class DefinitionGroupContext:
|
2020-08-15 18:38:08 +00:00
|
|
|
private val xs: ListBuffer[Definition[_]] =
|
|
|
|
ListBuffer()
|
|
|
|
|
2023-06-19 09:30:17 +00:00
|
|
|
def push[A](x: A)(using ev: NamedResource[A]): Unit =
|
2020-08-26 06:15:40 +00:00
|
|
|
ev
|
|
|
|
.toDefinitions(x)
|
|
|
|
.foreach(xs.append)
|
2020-08-15 18:38:08 +00:00
|
|
|
|
2020-08-15 18:45:08 +00:00
|
|
|
def toGroup(s: String): DefinitionGroup =
|
|
|
|
DefinitionGroup(s, xs.toList)
|
2020-08-15 18:38:08 +00:00
|
|
|
|
2020-08-26 06:37:12 +00:00
|
|
|
/**
|
2021-09-06 08:16:08 +00:00
|
|
|
* @param comment
|
|
|
|
* Typically used by resources to describe their type safety
|
2020-08-26 06:37:12 +00:00
|
|
|
*/
|
2023-06-19 09:30:17 +00:00
|
|
|
case class Definition[A](name: String, x: A, comment: Option[String])(using ev: DefinitionValue[A]):
|
2020-08-16 05:17:39 +00:00
|
|
|
lazy val value: String =
|
2020-08-26 07:16:19 +00:00
|
|
|
ev
|
|
|
|
.value(x)
|
2020-08-15 18:38:08 +00:00
|
|
|
|
2022-02-14 23:11:45 +00:00
|
|
|
object Definition:
|
2023-06-19 09:33:38 +00:00
|
|
|
given namedResourceForDefinition[A]: NamedResource[Definition[A]] =
|
2022-09-07 15:21:22 +00:00
|
|
|
new NamedResource[Definition[A]]:
|
2020-08-26 06:15:40 +00:00
|
|
|
def toDefinitions(x: Definition[A]): List[Definition[_]] =
|
|
|
|
List(x)
|
2020-08-26 06:32:27 +00:00
|
|
|
|
2020-08-26 07:16:19 +00:00
|
|
|
def apply[A: DefinitionValue](name: String, x: A): Definition[A] =
|
2020-08-26 06:32:27 +00:00
|
|
|
Definition(name, x, None)
|
|
|
|
|
2020-08-26 07:16:19 +00:00
|
|
|
def apply[A: DefinitionValue](name: String, x: A, comment: String): Definition[A] =
|
2020-08-26 06:32:27 +00:00
|
|
|
Definition(name, x, comment.some)
|
2020-08-26 06:06:54 +00:00
|
|
|
|
2022-02-14 23:11:45 +00:00
|
|
|
class AsmBlockContext:
|
2020-08-15 18:38:08 +00:00
|
|
|
private val xs: ListBuffer[Statement] =
|
|
|
|
ListBuffer()
|
|
|
|
|
|
|
|
def push(x: Statement): Unit =
|
|
|
|
xs.append(x)
|