mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-22 16:31:02 +00:00
Array filters (@word, @word_be)
This commit is contained in:
parent
0f453e2d2c
commit
24a3943501
@ -12,6 +12,8 @@
|
||||
|
||||
* Added 24-bit `farword` type.
|
||||
|
||||
* Special array layouts, e.g. `@word`.
|
||||
|
||||
* Fixed invalid offsets for branching instructions.
|
||||
|
||||
* Fixed incorrectly overlapping local variables.
|
||||
|
@ -66,6 +66,15 @@ An array is initialized with either:
|
||||
|
||||
* a `for`-style expression
|
||||
|
||||
* a format, followed by an array initializer:
|
||||
|
||||
* `@word` (=`@word_le`): for every term of the array initializer, emit two bytes, first being the low byte of the value, second being the high byte:
|
||||
`@word [$1122]` is equivalent to `[$22, $11]`
|
||||
|
||||
* `@word_be` – like the above, but opposite:
|
||||
`@word_be [$1122]` is equivalent to `[$11, $22]`
|
||||
|
||||
|
||||
* a list of byte literals and/or other array initializers, surrounded by brackets:
|
||||
|
||||
|
||||
|
2
src/main/scala/millfork/env/Constant.scala
vendored
2
src/main/scala/millfork/env/Constant.scala
vendored
@ -7,6 +7,8 @@ object Constant {
|
||||
val Zero: Constant = NumericConstant(0, 1)
|
||||
val One: Constant = NumericConstant(1, 1)
|
||||
|
||||
def apply(i: Long): Constant = NumericConstant(i, minimumSize(i))
|
||||
|
||||
def error(msg: String, position: Option[Position] = None): Constant = {
|
||||
ErrorReporting.error(msg, position)
|
||||
Zero
|
||||
|
26
src/main/scala/millfork/env/Environment.scala
vendored
26
src/main/scala/millfork/env/Environment.scala
vendored
@ -365,6 +365,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
|
||||
}
|
||||
}
|
||||
|
||||
//noinspection ScalaUnnecessaryParentheses,ZeroIndexToHead
|
||||
def eval(e: Expression): Option[Constant] = {
|
||||
e match {
|
||||
case LiteralExpression(value, size) => Some(NumericConstant(value, size))
|
||||
@ -410,6 +411,30 @@ class Environment(val parent: Option[Environment], val prefix: String) {
|
||||
ErrorReporting.error("Invalid number of parameters for `lo`", e.position)
|
||||
None
|
||||
}
|
||||
case "sin" =>
|
||||
if (params.size == 2) {
|
||||
(eval(params(0)) -> eval(params(1))) match {
|
||||
case (Some(NumericConstant(angle, _)), Some(NumericConstant(scale, _))) =>
|
||||
val value = (scale * math.sin(angle * math.Pi / 128)).toInt
|
||||
Some(Constant(value))
|
||||
case _ => None
|
||||
}
|
||||
} else {
|
||||
ErrorReporting.error("Invalid number of parameters for `sin`", e.position)
|
||||
None
|
||||
}
|
||||
case "cos" =>
|
||||
if (params.size == 2) {
|
||||
(eval(params(0)) -> eval(params(1))) match {
|
||||
case (Some(NumericConstant(angle, _)), Some(NumericConstant(scale, _))) =>
|
||||
val value = (scale * math.cos(angle * math.Pi / 128)).toInt
|
||||
Some(Constant(value))
|
||||
case _ => None
|
||||
}
|
||||
} else {
|
||||
ErrorReporting.error("Invalid number of parameters for `cos`", e.position)
|
||||
None
|
||||
}
|
||||
case "nonet" =>
|
||||
params match {
|
||||
case List(FunctionCallExpression("<<", ps@List(_, _))) =>
|
||||
@ -711,6 +736,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
|
||||
def extractArrayContents(contents1: ArrayContents): List[Expression] = contents1 match {
|
||||
case LiteralContents(xs) => xs
|
||||
case CombinedContents(xs) => xs.flatMap(extractArrayContents)
|
||||
case pc@ProcessedContents(f, xs) => pc.getAllExpressions
|
||||
case ForLoopContents(v, start, end, direction, body) =>
|
||||
(eval(start), eval(end)) match {
|
||||
case (Some(NumericConstant(s, sz1)), Some(NumericConstant(e, sz2))) =>
|
||||
|
@ -159,6 +159,24 @@ case class CombinedContents(contents: List[ArrayContents]) extends ArrayContents
|
||||
CombinedContents(contents.map(_.replaceVariable(variableToReplace, expression)))
|
||||
}
|
||||
|
||||
case class ProcessedContents(processor: String, values: ArrayContents) extends ArrayContents {
|
||||
override def getAllExpressions: List[Expression] = processor match {
|
||||
case "word" | "word_le" =>
|
||||
values.getAllExpressions.flatMap(expr => List(
|
||||
FunctionCallExpression("lo", List(expr)),
|
||||
FunctionCallExpression("hi", List(expr))
|
||||
))
|
||||
case "word_be" =>
|
||||
values.getAllExpressions.flatMap(expr => List(
|
||||
FunctionCallExpression("hi", List(expr)),
|
||||
FunctionCallExpression("lo", List(expr))
|
||||
))
|
||||
}
|
||||
|
||||
override def replaceVariable(variableToReplace: String, expression: Expression): ArrayContents =
|
||||
ProcessedContents(processor, values.replaceVariable(variableToReplace, expression))
|
||||
}
|
||||
|
||||
case class ArrayDeclarationStatement(name: String,
|
||||
bank: Option[String],
|
||||
length: Option[Expression],
|
||||
|
@ -195,6 +195,13 @@ abstract class MfParser[T](filename: String, input: String, currentDirectory: St
|
||||
|
||||
def arrayListElement: P[ArrayContents] = arrayStringContents | arrayLoopContents | mfExpression(nonStatementLevel).map(e => LiteralContents(List(e)))
|
||||
|
||||
def arrayProcessedContents: P[ArrayContents] = for {
|
||||
_ <- "@" ~/ HWS
|
||||
filter <- identifier
|
||||
_ <- AWS
|
||||
contents <- arrayContents
|
||||
} yield ProcessedContents(filter, contents)
|
||||
|
||||
def arrayListContents: P[ArrayContents] = ("[" ~/ AWS ~/ arrayListElement.rep(sep = AWS ~ "," ~/ AWS) ~ AWS ~ "]" ~/ Pass).map(c => CombinedContents(c.toList))
|
||||
|
||||
val doubleQuotedString: P[List[Char]] = P("\"" ~/ CharsWhile(c => c != '\"' && c != '\n' && c != '\r').! ~ "\"").map(_.toList)
|
||||
@ -259,7 +266,7 @@ abstract class MfParser[T](filename: String, input: String, currentDirectory: St
|
||||
ForLoopContents(identifier, start, end, fixedDirection, body)
|
||||
}
|
||||
|
||||
def arrayContents: P[ArrayContents] = arrayListContents | arrayLoopContents | arrayFileContents | arrayStringContents
|
||||
def arrayContents: P[ArrayContents] = arrayProcessedContents | arrayListContents | arrayLoopContents | arrayFileContents | arrayStringContents
|
||||
|
||||
def arrayContentsForAsm: P[RawBytesStatement] = (arrayListContents | arrayStringContents).map(RawBytesStatement)
|
||||
|
||||
|
@ -244,4 +244,17 @@ class ArraySuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
test("Array filters") {
|
||||
EmuCrossPlatformBenchmarkRun(CpuFamily.M6502, CpuFamily.I80)(
|
||||
"""
|
||||
| array x = @word [$1144]
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
| output = x[0]
|
||||
| }
|
||||
""".stripMargin) { m =>
|
||||
m.readByte(0xc000) should equal(0x44)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user