From 2665f18c77408f70ad9a30ad64d7eacf1103bd2b Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Sat, 3 Feb 2018 17:49:29 +0100 Subject: [PATCH] Macro expansion fix, improved constant folding --- .gitignore | 1 + .../scala/millfork/compiler/MfCompiler.scala | 28 ++++++++++++++---- src/main/scala/millfork/env/Constant.scala | 28 ++++++++++++++++++ src/test/scala/millfork/test/MacroSuite.scala | 29 +++++++++++++++++++ 4 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 src/test/scala/millfork/test/MacroSuite.scala diff --git a/.gitignore b/.gitignore index 98652582..bb6e033d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ project/target project/project/target/ stuff releases +src/test/scala/experiments/ # hidden files *.~ diff --git a/src/main/scala/millfork/compiler/MfCompiler.scala b/src/main/scala/millfork/compiler/MfCompiler.scala index 3ad388dc..c012bd2b 100644 --- a/src/main/scala/millfork/compiler/MfCompiler.scala +++ b/src/main/scala/millfork/compiler/MfCompiler.scala @@ -771,10 +771,23 @@ object MfCompiler { } } case SumExpression(params, decimal) => - assertAllBytesForSum("Long addition not supported", ctx, params) - val calculate = BuiltIns.compileAddition(ctx, params, decimal = decimal) - val store = expressionStorageFromAX(ctx, exprTypeAndVariable, expr.position) - calculate ++ store + val a = params.map{case (n, p) => env.eval(p).map(n -> _)} + if (a.forall(_.isDefined)) { + val value = a.foldLeft(Constant.Zero){(c, pair) => + val Some((neg, v)) = pair + CompoundConstant(if (decimal) { + if (neg) MathOperator.DecimalMinus else MathOperator.DecimalPlus + } else { + if (neg) MathOperator.Minus else MathOperator.Plus + }, c, v) + } + exprTypeAndVariable.map(x => compileConstant(ctx, value.quickSimplify, x._2)).getOrElse(Nil) + } else { + assertAllBytesForSum("Long addition not supported", ctx, params) + val calculate = BuiltIns.compileAddition(ctx, params, decimal = decimal) + val store = expressionStorageFromAX(ctx, exprTypeAndVariable, expr.position) + calculate ++ store + } case SeparateBytesExpression(h, l) => exprTypeAndVariable.fold { // TODO: order? @@ -1367,7 +1380,10 @@ object MfCompiler { case IfStatement(c, t, e) => IfStatement(f(c), t.map(gx), e.map(gx)) case s:AssemblyStatement => s.copy(expression = f(s.expression)) case Assignment(d,s) => Assignment(fx(d), f(s)) - case _ => ??? + case BlockStatement(s) => BlockStatement(s.map(gx)) + case _ => + println(stmt) + ??? } } @@ -1416,7 +1432,7 @@ object MfCompiler { } else { params.zip(normalParams).foreach{ case (v@VariableExpression(_), MemoryVariable(paramName, paramType, _)) => - actualCode = actualCode.map(stmt => replaceVariable(stmt, paramName, v).asInstanceOf[ExecutableStatement]) + actualCode = actualCode.map(stmt => replaceVariable(stmt, paramName.stripPrefix(i.environment.prefix), v).asInstanceOf[ExecutableStatement]) case _ => ErrorReporting.error(s"Parameters to macro functions have to be variables", position) } diff --git a/src/main/scala/millfork/env/Constant.scala b/src/main/scala/millfork/env/Constant.scala index 1375bd1c..19d7d90c 100644 --- a/src/main/scala/millfork/env/Constant.scala +++ b/src/main/scala/millfork/env/Constant.scala @@ -182,6 +182,34 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co case _ => } NumericConstant(value, size) + case (NumericConstant(0, 1), c) => + operator match { + case MathOperator.Plus => c + case MathOperator.Minus => CompoundConstant(operator, l, r) + case MathOperator.Times => Constant.Zero + case MathOperator.Shl => Constant.Zero + case MathOperator.Shr => Constant.Zero + case MathOperator.Shl9 => Constant.Zero + case MathOperator.Shr9 => Constant.Zero + case MathOperator.Exor => c + case MathOperator.Or => c + case MathOperator.And => Constant.Zero + case _ => CompoundConstant(operator, l, r) + } + case (c, NumericConstant(0, 1)) => + operator match { + case MathOperator.Plus => c + case MathOperator.Minus => c + case MathOperator.Times => Constant.Zero + case MathOperator.Shl => c + case MathOperator.Shr => c + case MathOperator.Shl9 => c + case MathOperator.Shr9 => c + case MathOperator.Exor => c + case MathOperator.Or => c + case MathOperator.And => Constant.Zero + case _ => CompoundConstant(operator, l, r) + } case _ => CompoundConstant(operator, l, r) } } diff --git a/src/test/scala/millfork/test/MacroSuite.scala b/src/test/scala/millfork/test/MacroSuite.scala new file mode 100644 index 00000000..00f2aa91 --- /dev/null +++ b/src/test/scala/millfork/test/MacroSuite.scala @@ -0,0 +1,29 @@ +package millfork.test + +import millfork.test.emu.EmuBenchmarkRun +import org.scalatest.{FunSuite, Matchers} + +/** + * @author Karol Stasiak + */ +class MacroSuite extends FunSuite with Matchers { + + test("Most basic test") { + EmuBenchmarkRun( + """ + | macro void run(byte x) { + | output = x + | } + | + | byte output @$c000 + | + | void main () { + | byte a + | a = 7 + | run(a) + | } + """.stripMargin) { m => + m.readByte(0xc000) should equal(7) + } + } +}