2022-12-05 22:19:50 +00:00
|
|
|
package com.htmlism.firepower.core
|
2022-12-04 21:49:05 +00:00
|
|
|
|
|
|
|
sealed trait AsmBlock
|
|
|
|
|
2022-12-05 22:19:50 +00:00
|
|
|
object AsmBlock:
|
|
|
|
case class CommentBlock(xs: List[String]) extends AsmBlock
|
2022-12-04 21:49:05 +00:00
|
|
|
|
2022-12-05 22:19:50 +00:00
|
|
|
object CommentBlock:
|
|
|
|
def fromMultiline(s: String): CommentBlock =
|
|
|
|
CommentBlock(s.split("\\n").toList)
|
2022-12-04 21:56:03 +00:00
|
|
|
|
2022-12-06 21:39:00 +00:00
|
|
|
case class DefinesBlock(xs: List[(String, Int)]) extends AsmBlock
|
2022-12-06 20:38:39 +00:00
|
|
|
|
2022-12-05 22:19:50 +00:00
|
|
|
case class NamedCodeBlock(name: String, comment: Option[String], intents: List[AsmBlock.Intent]) extends AsmBlock
|
|
|
|
|
|
|
|
case class AnonymousCodeBlock(intents: List[AsmBlock.Intent]) extends AsmBlock
|
2022-12-04 21:56:03 +00:00
|
|
|
|
2022-12-04 23:17:31 +00:00
|
|
|
def interFlatMap[A, B](xs: List[A])(x: List[B], f: A => List[B]): List[B] =
|
|
|
|
xs match
|
|
|
|
case head :: tail =>
|
|
|
|
f(head) ::: tail.flatMap(a => x ::: f(a))
|
|
|
|
|
|
|
|
case Nil =>
|
|
|
|
Nil
|
|
|
|
|
2022-12-04 22:23:42 +00:00
|
|
|
def toComment(s: String): String =
|
|
|
|
"; " + s
|
|
|
|
|
|
|
|
def withIndent(s: String): String =
|
|
|
|
" " + s
|
|
|
|
|
2022-12-06 21:53:40 +00:00
|
|
|
def toHex(n: Int): String =
|
|
|
|
val hex =
|
|
|
|
if (n < 16 * 16)
|
|
|
|
String.format("%1$02x", n)
|
|
|
|
else if (n < 16 * 16 * 16)
|
|
|
|
String.format("%1$03x", n)
|
|
|
|
else
|
|
|
|
String.format("%1$04x", n)
|
|
|
|
|
|
|
|
"$" + hex.toUpperCase
|
|
|
|
|
2022-12-04 23:17:31 +00:00
|
|
|
def toLines(xs: AsmBlock): List[String] =
|
2022-12-04 21:49:05 +00:00
|
|
|
xs match
|
|
|
|
case CommentBlock(ys) =>
|
2022-12-04 23:17:31 +00:00
|
|
|
ys.map(toComment)
|
2022-12-04 21:49:05 +00:00
|
|
|
|
2022-12-06 20:38:39 +00:00
|
|
|
case DefinesBlock(kvs) =>
|
2022-12-06 20:47:00 +00:00
|
|
|
val maximumLength =
|
|
|
|
kvs
|
|
|
|
.map(_._1.length)
|
|
|
|
.max
|
|
|
|
|
2022-12-06 20:38:39 +00:00
|
|
|
kvs
|
|
|
|
.map { case (k, v) =>
|
2022-12-06 21:53:40 +00:00
|
|
|
String.format(s"define %-${maximumLength}s ${toHex(v)}", k)
|
2022-12-06 20:38:39 +00:00
|
|
|
}
|
|
|
|
|
2022-12-04 22:30:36 +00:00
|
|
|
case NamedCodeBlock(label, oComment, intents) =>
|
2022-12-04 22:23:42 +00:00
|
|
|
val headerParagraph =
|
2022-12-04 23:17:31 +00:00
|
|
|
List(label + ":") ++ oComment.map(toComment).map(withIndent).toList
|
2022-12-04 22:23:42 +00:00
|
|
|
|
|
|
|
val intentParagraphs =
|
2022-12-04 23:26:53 +00:00
|
|
|
intents.map(Intent.toLines)
|
2022-12-04 22:23:42 +00:00
|
|
|
|
2022-12-04 23:26:53 +00:00
|
|
|
interFlatMap(headerParagraph :: intentParagraphs)(List(""), identity)
|
2022-12-04 21:56:03 +00:00
|
|
|
|
2022-12-04 22:30:36 +00:00
|
|
|
case AnonymousCodeBlock(intents) =>
|
2022-12-04 23:17:31 +00:00
|
|
|
interFlatMap(intents)(List(""), Intent.toLines)
|
2022-12-04 22:15:29 +00:00
|
|
|
|
|
|
|
case class Intent(label: Option[String], instructions: List[Intent.Instruction])
|
|
|
|
|
|
|
|
object Intent:
|
|
|
|
case class Instruction(code: String, comment: Option[String])
|
|
|
|
|
2022-12-04 23:17:31 +00:00
|
|
|
def toLines(x: Intent): List[String] =
|
2022-12-06 22:20:30 +00:00
|
|
|
val comment =
|
|
|
|
x.label.map(toComment).map(withIndent).toList
|
|
|
|
|
|
|
|
val maximumLength =
|
|
|
|
x
|
|
|
|
.instructions
|
|
|
|
.map(_.code.length)
|
|
|
|
.max
|
|
|
|
|
|
|
|
val instructions =
|
|
|
|
x
|
|
|
|
.instructions
|
|
|
|
.map { i =>
|
|
|
|
i.comment match
|
|
|
|
case Some(c) =>
|
|
|
|
String.format(s"%-${maximumLength}s", i.code) + " " + toComment(c)
|
|
|
|
|
|
|
|
case None =>
|
|
|
|
i.code
|
|
|
|
}
|
|
|
|
.map(withIndent)
|
|
|
|
|
|
|
|
comment ++ instructions
|