From 516d7eae2639f9e9fbad767c522c90af83adac42 Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Fri, 16 Mar 2018 00:34:24 +0100 Subject: [PATCH] Removal of the <<<< operator; nonet operation improvements Use `nonet(a << b)` instead of `a <<<< b` --- .../scala/millfork/compiler/BuiltIns.scala | 11 ----------- .../millfork/compiler/ExpressionCompiler.scala | 8 +------- src/main/scala/millfork/env/Constant.scala | 18 +++++++++++++++--- src/main/scala/millfork/env/Environment.scala | 17 ++++++++++++++--- src/main/scala/millfork/output/Assembler.scala | 4 ++++ src/main/scala/millfork/parser/MfParser.scala | 2 +- .../test/AssemblyOptimizationSuite.scala | 2 +- src/test/scala/millfork/test/NonetSuite.scala | 8 ++++---- 8 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/main/scala/millfork/compiler/BuiltIns.scala b/src/main/scala/millfork/compiler/BuiltIns.scala index 3f18280c..c9efe0d1 100644 --- a/src/main/scala/millfork/compiler/BuiltIns.scala +++ b/src/main/scala/millfork/compiler/BuiltIns.scala @@ -227,17 +227,6 @@ object BuiltIns { } } - @deprecated - def compileNonetLeftShift(ctx: CompilationContext, lhs: Expression, rhs: Expression): List[AssemblyLine] = { - val label = MfCompiler.nextLabel("sh") - compileShiftOps(ASL, ctx, lhs, rhs) ++ List( - AssemblyLine.immediate(LDX, 0), - AssemblyLine.relative(BCC, label), - AssemblyLine.implied(INX), - AssemblyLine.label(label) - ) - } - def compileInPlaceByteShiftOps(opcode: Opcode.Value, ctx: CompilationContext, lhs: LhsExpression, rhs: Expression): List[AssemblyLine] = { val env = ctx.env val b = env.get[Type]("byte") diff --git a/src/main/scala/millfork/compiler/ExpressionCompiler.scala b/src/main/scala/millfork/compiler/ExpressionCompiler.scala index 8a5c0560..08f8906d 100644 --- a/src/main/scala/millfork/compiler/ExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/ExpressionCompiler.scala @@ -62,7 +62,6 @@ object ExpressionCompiler { case FunctionCallExpression("<<'", params) => b case FunctionCallExpression(">>'", params) => b case FunctionCallExpression(">>>>", params) => b - case FunctionCallExpression("<<<<", params) => w case FunctionCallExpression("&&", params) => bool case FunctionCallExpression("||", params) => bool case FunctionCallExpression("^^", params) => bool @@ -832,7 +831,7 @@ object ExpressionCompiler { if (addends.size > 2) { ErrorReporting.warn("Nonet addition works correctly only for two operands", ctx.options, expr.position) } - case FunctionCallExpression("+" | "+'" | "<<" | "<<<<" | "<<'" | "nonet", _) => // ok + case FunctionCallExpression("+" | "+'" | "<<" | "<<'" | "nonet", _) => // ok case _ => ErrorReporting.warn("Unspecified nonet operation, results might be unpredictable", ctx.options, expr.position) } @@ -895,11 +894,6 @@ object ExpressionCompiler { case v: LhsExpression => 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) case "<<" => val (l, r, size) = assertBinary(ctx, params) size match { diff --git a/src/main/scala/millfork/env/Constant.scala b/src/main/scala/millfork/env/Constant.scala index 8509776f..de5b477c 100644 --- a/src/main/scala/millfork/env/Constant.scala +++ b/src/main/scala/millfork/env/Constant.scala @@ -150,8 +150,8 @@ case class SubbyteConstant(base: Constant, index: Int) extends Constant { } object MathOperator extends Enumeration { - val Plus, Minus, Times, Shl, Shr, Shl9, Shr9, - DecimalPlus, DecimalMinus, DecimalTimes, DecimalShl, DecimalShr, + val Plus, Minus, Times, Shl, Shr, Shl9, Shr9, Plus9, DecimalPlus9, + DecimalPlus, DecimalMinus, DecimalTimes, DecimalShl, DecimalShl9, DecimalShr, And, Or, Exor = Value } @@ -170,6 +170,7 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co case MathOperator.Shl => lv << rv case MathOperator.Shr => lv >> rv case MathOperator.Shl9 => (lv << rv) & 0x1ff + case MathOperator.Plus9 => (lv + rv) & 0x1ff case MathOperator.Shr9 => (lv & 0x1ff) >> rv case MathOperator.Exor => lv ^ rv case MathOperator.Or => lv | rv @@ -177,6 +178,8 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co case _ => return this } operator match { + case MathOperator.Plus9 | MathOperator.DecimalPlus9 => + size = 2 case MathOperator.Times | MathOperator.Shl => val mask = (1 << (size * 8)) - 1 if (value != (value & mask)){ @@ -188,6 +191,9 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co case (NumericConstant(0, 1), c) => operator match { case MathOperator.Plus => c + case MathOperator.Plus9 => c + case MathOperator.DecimalPlus => c + case MathOperator.DecimalPlus9 => c case MathOperator.Minus => CompoundConstant(operator, l, r) case MathOperator.Times => Constant.Zero case MathOperator.Shl => Constant.Zero @@ -202,6 +208,9 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co case (c, NumericConstant(0, 1)) => operator match { case MathOperator.Plus => c + case MathOperator.Plus9 => c + case MathOperator.DecimalPlus => c + case MathOperator.DecimalPlus9 => c case MathOperator.Minus => c case MathOperator.Times => Constant.Zero case MathOperator.Shl => c @@ -259,16 +268,19 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co override def toString: String = { operator match { case Plus => f"$plhs + $prhs" + case Plus9 => f"nonet($plhs + $prhs)" case Minus => f"$plhs - $prhs" case Times => f"$plhs * $prhs" case Shl => f"$plhs << $prhs" case Shr => f"$plhs >> $prhs" - case Shl9 => f"$plhs <<<< $prhs" + case Shl9 => f"nonet($plhs << $prhs)" case Shr9 => f"$plhs >>>> $prhs" case DecimalPlus => f"$plhs +' $prhs" + case DecimalPlus9 => f"nonet($plhs +' $prhs)" case DecimalMinus => f"$plhs -' $prhs" case DecimalTimes => f"$plhs *' $prhs" case DecimalShl => f"$plhs <<' $prhs" + case DecimalShl9 => f"nonet($plhs <<' $prhs)" case DecimalShr => f"$plhs >>' $prhs" case And => f"$plhs & $prhs" case Or => f"$plhs | $prhs" diff --git a/src/main/scala/millfork/env/Environment.scala b/src/main/scala/millfork/env/Environment.scala index 10d55bed..fa96b36b 100644 --- a/src/main/scala/millfork/env/Environment.scala +++ b/src/main/scala/millfork/env/Environment.scala @@ -278,7 +278,7 @@ class Environment(val parent: Option[Environment], val prefix: String) { "<<" | ">>" | "<<'" | ">>'" | "&" | "|" | "^" | - ">>>>" | "<<<<" | + ">>>>" | "*" | "*'", _)) => variable -> constant case Some(FunctionCallExpression(fname, _)) => maybeGet[Thing](fname) match { @@ -332,6 +332,19 @@ class Environment(val parent: Option[Environment], val prefix: String) { } yield hc.asl(8) + lc case FunctionCallExpression(name, params) => name match { + case "nonet" => + params match { + case List(FunctionCallExpression("<<", ps@List(_, _))) => + constantOperation(MathOperator.Shl9, ps) + case List(FunctionCallExpression("<<'", ps@List(_, _))) => + constantOperation(MathOperator.DecimalShl9, ps) + case List(SumExpression(ps@List((true,_),(true,_)), false)) => + constantOperation(MathOperator.Plus9, ps.map(_._2)) + case List(SumExpression(ps@List((true,_),(true,_)), true)) => + constantOperation(MathOperator.DecimalPlus9, ps.map(_._2)) + case _ => + None + } case ">>'" => constantOperation(MathOperator.DecimalShr, params) case "<<'" => @@ -340,8 +353,6 @@ class Environment(val parent: Option[Environment], val prefix: String) { constantOperation(MathOperator.Shr, params) case "<<" => constantOperation(MathOperator.Shl, params) - case "<<<<" => - constantOperation(MathOperator.Shl9, params) case ">>>>" => constantOperation(MathOperator.Shr9, params) case "*'" => diff --git a/src/main/scala/millfork/output/Assembler.scala b/src/main/scala/millfork/output/Assembler.scala index f2a6e2ee..c4d9f2cd 100644 --- a/src/main/scala/millfork/output/Assembler.scala +++ b/src/main/scala/millfork/output/Assembler.scala @@ -99,14 +99,18 @@ class Assembler(private val program: Program, private val rootEnv: Environment, val r = deepConstResolve(rc) operator match { case MathOperator.Plus => l + r + case MathOperator.Plus9 => (l + r) & 0x1ff case MathOperator.Minus => l - r case MathOperator.Times => l * r case MathOperator.Shl => l << r + case MathOperator.Shl9 => (l << r) & 0x1ff case MathOperator.Shr => l >>> r case MathOperator.DecimalPlus => asDecimal(l, r, _ + _) + case MathOperator.DecimalPlus9 => asDecimal(l, r, _ + _) & 0x1ff case MathOperator.DecimalMinus => asDecimal(l, r, _ - _) case MathOperator.DecimalTimes => asDecimal(l, r, _ * _) case MathOperator.DecimalShl => asDecimal(l, 1 << r, _ * _) + case MathOperator.DecimalShl9 => asDecimal(l, 1 << r, _ * _) & 0x1ff case MathOperator.DecimalShr => asDecimal(l, 1 << r, _ / _) case MathOperator.And => l & r case MathOperator.Exor => l ^ r diff --git a/src/main/scala/millfork/parser/MfParser.scala b/src/main/scala/millfork/parser/MfParser.scala index b48a0ef0..9baf00de 100644 --- a/src/main/scala/millfork/parser/MfParser.scala +++ b/src/main/scala/millfork/parser/MfParser.scala @@ -130,7 +130,7 @@ case class MfParser(filename: String, input: String, currentDirectory: String, o List("&&"), List("==", "<=", ">=", "!=", "<", ">"), List(":"), - List("+'", "-'", "<<'", ">>'", "<<<<", ">>>>", "+", "-", "&", "|", "^", "<<", ">>"), + List("+'", "-'", "<<'", ">>'", ">>>>", "+", "-", "&", "|", "^", "<<", ">>"), List("*'", "*")) val nonStatementLevel = 1 // everything but not `=` diff --git a/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala b/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala index f38ef1a1..9aac53fb 100644 --- a/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala +++ b/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala @@ -310,7 +310,7 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers { | byte source @$C002 | void main () { | init() - | output += source <<<< 1 + | output += nonet(source << 1) | } | void init() { | output = 0 diff --git a/src/test/scala/millfork/test/NonetSuite.scala b/src/test/scala/millfork/test/NonetSuite.scala index 19d62d1b..6e7001d2 100644 --- a/src/test/scala/millfork/test/NonetSuite.scala +++ b/src/test/scala/millfork/test/NonetSuite.scala @@ -37,10 +37,10 @@ class NonetSuite extends FunSuite with Matchers { | void main () { | byte a | a = 3 - | output0 = a <<<< 1 - | output1 = a <<<< 2 - | output2 = a <<<< 6 - | output3 = a <<<< 7 + | output0 = nonet(a << 1) + | output1 = nonet(a << 2) + | output2 = nonet(a << 6) + | output3 = nonet(a << 7) | } """.stripMargin) { m => m.readWord(0xc000) should equal(0x06)