mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-23 08:29:35 +00:00
nonet() operator
This commit is contained in:
parent
e95d403752
commit
59cf1e06b4
@ -19,7 +19,7 @@
|
||||
* Removed command line flag `--detailed-flow`.
|
||||
Detailed flow analysis was slow, broken, hard to maintain, and didn't even help that much.
|
||||
|
||||
* Added `*'=` and `<<<<` operators.
|
||||
* Added `*'=` and `nonet` operators. (Also, the `<<<<` operator, but it will be phased out before 0.2 and replaced by `nonet(a << b)`.)
|
||||
|
||||
* Added support for zeropage pseudoregisters, allowing for some operators work with more types of operands.
|
||||
|
||||
|
@ -36,6 +36,8 @@ where `11111` is a sequential number and `xx` is the type:
|
||||
|
||||
* `is` – optimized addition of carry using undocumented instructions
|
||||
|
||||
* `no` – nonet to word extension caused by the `nonet` operator
|
||||
|
||||
* `od` – end of a `do-while` statement
|
||||
|
||||
* `or` – logical alternative short-circuiting
|
||||
|
@ -39,6 +39,7 @@ object ExpressionCompiler {
|
||||
if (getExpressionType(ctx, lo).size > 1) ErrorReporting.error("Lo byte too large", lo.position)
|
||||
w
|
||||
case SumExpression(params, _) => b
|
||||
case FunctionCallExpression("nonet", params) => w
|
||||
case FunctionCallExpression("not", params) => bool
|
||||
case FunctionCallExpression("hi", params) => bool
|
||||
case FunctionCallExpression("lo", params) => bool
|
||||
@ -805,6 +806,32 @@ object ExpressionCompiler {
|
||||
} else compilation
|
||||
}
|
||||
}
|
||||
case "nonet" =>
|
||||
if (params.length != 1) {
|
||||
ErrorReporting.error("Invalid number of parameters", f.position)
|
||||
Nil
|
||||
} else {
|
||||
assertAllBytes("Nonet argument has to be a byte", ctx, params)
|
||||
params.head match {
|
||||
case SumExpression(addends, _) =>
|
||||
if (addends.exists(a => !a._1)) {
|
||||
ErrorReporting.warn("Nonet subtraction may not work as expected", ctx.options, expr.position)
|
||||
}
|
||||
if (addends.size > 2) {
|
||||
ErrorReporting.warn("Nonet addition works correctly only for two operands", ctx.options, expr.position)
|
||||
}
|
||||
case FunctionCallExpression("+" | "+'" | "<<" | "<<<<" | "<<'" | "nonet", _) => // ok
|
||||
case _ =>
|
||||
ErrorReporting.warn("Unspecified nonet operation, results might be unpredictable", ctx.options, expr.position)
|
||||
}
|
||||
val label = MfCompiler.nextLabel("no")
|
||||
compile(ctx, params.head, Some(b -> RegisterVariable(Register.A, b)), BranchSpec.None) ++ List(
|
||||
AssemblyLine.immediate(LDX, 0),
|
||||
AssemblyLine.relative(BCC, label),
|
||||
AssemblyLine.implied(INX),
|
||||
AssemblyLine.label(label)
|
||||
) ++ expressionStorageFromAX(ctx, exprTypeAndVariable, expr.position)
|
||||
}
|
||||
case "&&" =>
|
||||
assertBool(ctx, params, 2)
|
||||
val a = params.head
|
||||
@ -851,6 +878,7 @@ object ExpressionCompiler {
|
||||
BuiltIns.compileNonetOps(ctx, v, r)
|
||||
}
|
||||
case "<<<<" =>
|
||||
ErrorReporting.warn("`x <<<< y` is obsolete, use `nonet(x << y)`", ctx.options, expr.position)
|
||||
assertAllBytes("Long shift ops not supported", ctx, params)
|
||||
val (l, r, 1) = assertBinary(ctx, params)
|
||||
BuiltIns.compileNonetLeftShift(ctx, l, r)
|
||||
|
@ -841,5 +841,5 @@ class Environment(val parent: Option[Environment], val prefix: String) {
|
||||
}
|
||||
|
||||
object Environment {
|
||||
val predefinedFunctions = Set("not", "hi", "lo")
|
||||
val predefinedFunctions = Set("not", "hi", "lo", "nonet")
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.test.emu.EmuUnoptimizedRun
|
||||
import millfork.test.emu.{EmuBenchmarkRun, EmuUnoptimizedRun}
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -28,7 +28,7 @@ class NonetSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Nonet left shift") {
|
||||
val m = EmuUnoptimizedRun(
|
||||
EmuBenchmarkRun(
|
||||
"""
|
||||
| word output0 @$c000
|
||||
| word output1 @$c002
|
||||
@ -42,10 +42,34 @@ class NonetSuite extends FunSuite with Matchers {
|
||||
| output2 = a <<<< 6
|
||||
| output3 = a <<<< 7
|
||||
| }
|
||||
""".stripMargin)
|
||||
""".stripMargin) { m =>
|
||||
m.readWord(0xc000) should equal(0x06)
|
||||
m.readWord(0xc002) should equal(0x0C)
|
||||
m.readWord(0xc004) should equal(0xC0)
|
||||
m.readWord(0xc006) should equal(0x180)
|
||||
}
|
||||
}
|
||||
|
||||
test("Nonet left shift 2") {
|
||||
EmuBenchmarkRun(
|
||||
"""
|
||||
| word output0 @$c000
|
||||
| word output1 @$c002
|
||||
| word output2 @$c004
|
||||
| word output3 @$c006
|
||||
| void main () {
|
||||
| byte a
|
||||
| a = 3
|
||||
| output0 = nonet(a << 1)
|
||||
| output1 = nonet(a << 2)
|
||||
| output2 = nonet(a << 6)
|
||||
| output3 = nonet(a << 7)
|
||||
| }
|
||||
""".stripMargin) { m =>
|
||||
m.readWord(0xc000) should equal(0x06)
|
||||
m.readWord(0xc002) should equal(0x0C)
|
||||
m.readWord(0xc004) should equal(0xC0)
|
||||
m.readWord(0xc006) should equal(0x180)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user