mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-23 08:29:35 +00:00
Better evaluation of the if function in constants
This commit is contained in:
parent
f676e74e38
commit
34ef8b8de9
26
src/main/scala/millfork/env/Constant.scala
vendored
26
src/main/scala/millfork/env/Constant.scala
vendored
@ -440,6 +440,7 @@ case class SubbyteConstant(base: Constant, index: Int) extends Constant {
|
|||||||
object MathOperator extends Enumeration {
|
object MathOperator extends Enumeration {
|
||||||
val Plus, Minus, Times, Shl, Shr, Shl9, Shr9, Plus9, DecimalPlus9,
|
val Plus, Minus, Times, Shl, Shr, Shl9, Shr9, Plus9, DecimalPlus9,
|
||||||
DecimalPlus, DecimalMinus, DecimalTimes, DecimalShl, DecimalShl9, DecimalShr,
|
DecimalPlus, DecimalMinus, DecimalTimes, DecimalShl, DecimalShl9, DecimalShr,
|
||||||
|
Equal, NotEqual, Less, LessEqual, Greater, GreaterEqual,
|
||||||
Minimum, Maximum,
|
Minimum, Maximum,
|
||||||
Divide, Modulo,
|
Divide, Modulo,
|
||||||
And, Or, Exor = Value
|
And, Or, Exor = Value
|
||||||
@ -599,7 +600,7 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
|
|||||||
case MathOperator.Exor => (lv ^ rv) & bitmask
|
case MathOperator.Exor => (lv ^ rv) & bitmask
|
||||||
case MathOperator.Or => lv | rv
|
case MathOperator.Or => lv | rv
|
||||||
case MathOperator.And => lv & rv & bitmask
|
case MathOperator.And => lv & rv & bitmask
|
||||||
case MathOperator.Divide if lv >= 0 && rv >= 0 => lv / rv
|
case MathOperator.Divide if lv >= 0 && rv > 0 => lv / rv
|
||||||
case MathOperator.Modulo if lv >= 0 && rv >= 0 => lv % rv
|
case MathOperator.Modulo if lv >= 0 && rv >= 0 => lv % rv
|
||||||
case MathOperator.DecimalPlus if ls == 1 && rs == 1 =>
|
case MathOperator.DecimalPlus if ls == 1 && rs == 1 =>
|
||||||
asDecimal(lv & 0xff, rv & 0xff, _ + _) & 0xff
|
asDecimal(lv & 0xff, rv & 0xff, _ + _) & 0xff
|
||||||
@ -692,6 +693,12 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
|
|||||||
case Exor => s"$plhs ^ $prhs"
|
case Exor => s"$plhs ^ $prhs"
|
||||||
case Divide => s"$plhs / $prhs"
|
case Divide => s"$plhs / $prhs"
|
||||||
case Modulo => s"$plhs %% $prhs"
|
case Modulo => s"$plhs %% $prhs"
|
||||||
|
case Equal => s"$plhs == $prhs"
|
||||||
|
case NotEqual => s"$plhs != $prhs"
|
||||||
|
case Greater => s"$plhs > $prhs"
|
||||||
|
case GreaterEqual => s"$plhs >= $prhs"
|
||||||
|
case Less=> s"$plhs < $prhs"
|
||||||
|
case LessEqual=> s"$plhs <= $prhs"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -783,3 +790,20 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
|
|||||||
|
|
||||||
override def extractLabels: List[String] = lhs.extractLabels ++ rhs.extractLabels
|
override def extractLabels: List[String] = lhs.extractLabels ++ rhs.extractLabels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case class IfConstant(cond: Constant, ifTrue: Constant, ifFalse: Constant) extends Constant {
|
||||||
|
|
||||||
|
override def toIntelString: String = s"if(${cond.toIntelString},${ifTrue.toIntelString},${ifFalse.toIntelString})"
|
||||||
|
|
||||||
|
override def toString: String = s"if(${cond.toString},${ifTrue.toString},${ifFalse.toString})"
|
||||||
|
|
||||||
|
override def requiredSize: Int = ifTrue.requiredSize max ifFalse.requiredSize
|
||||||
|
|
||||||
|
override def isRelatedTo(v: Thing): Boolean = cond.isRelatedTo(v) || ifTrue.isRelatedTo(v) || ifFalse.isRelatedTo(v)
|
||||||
|
|
||||||
|
override def refersTo(name: String): Boolean = cond.refersTo(name) || ifTrue.refersTo(name) || ifFalse.refersTo(name)
|
||||||
|
|
||||||
|
override def extractLabels: List[String] = cond.extractLabels ++ ifTrue.extractLabels ++ ifFalse.extractLabels
|
||||||
|
|
||||||
|
override def rootThingName: String = "?"
|
||||||
|
}
|
33
src/main/scala/millfork/env/Environment.scala
vendored
33
src/main/scala/millfork/env/Environment.scala
vendored
@ -840,7 +840,10 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
case Some(c) =>
|
case Some(c) =>
|
||||||
if (c.isProvablyGreaterOrEqualThan(1)) evalImpl(params(1), vv)
|
if (c.isProvablyGreaterOrEqualThan(1)) evalImpl(params(1), vv)
|
||||||
else if (c.isProvablyZero) evalImpl(params(2), vv)
|
else if (c.isProvablyZero) evalImpl(params(2), vv)
|
||||||
else None
|
else (evalImpl(params(1), vv), evalImpl(params(2), vv)) match {
|
||||||
|
case (Some(t), Some(f)) => Some(IfConstant(c, t, f))
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -887,15 +890,17 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
constantOperation(MathOperator.Exor, params, vv)
|
constantOperation(MathOperator.Exor, params, vv)
|
||||||
case "||" | "|" =>
|
case "||" | "|" =>
|
||||||
constantOperation(MathOperator.Or, params, vv)
|
constantOperation(MathOperator.Or, params, vv)
|
||||||
case ">" => evalComparisons(params, vv, _ > _)
|
case ">" => evalComparisons(params, vv, MathOperator.Greater, _ > _)
|
||||||
case "<" => evalComparisons(params, vv, _ < _)
|
case "<" => evalComparisons(params, vv, MathOperator.Less,_ < _)
|
||||||
case ">=" => evalComparisons(params, vv, _ >= _)
|
case ">=" => evalComparisons(params, vv, MathOperator.GreaterEqual,_ >= _)
|
||||||
case "<=" => evalComparisons(params, vv, _ <= _)
|
case "<=" => evalComparisons(params, vv, MathOperator.LessEqual,_ <= _)
|
||||||
case "==" => evalComparisons(params, vv, _ == _)
|
case "==" => evalComparisons(params, vv, MathOperator.Equal,_ == _)
|
||||||
case "!=" =>
|
case "!=" =>
|
||||||
sequence(params.map(p => evalImpl(p, vv))) match {
|
sequence(params.map(p => evalImpl(p, vv))) match {
|
||||||
case Some(List(NumericConstant(n1, _), NumericConstant(n2, _))) =>
|
case Some(List(NumericConstant(n1, _), NumericConstant(n2, _))) =>
|
||||||
Some(if (n1 != n2) Constant.One else Constant.Zero)
|
Some(if (n1 != n2) Constant.One else Constant.Zero)
|
||||||
|
case Some(List(c1, c2)) =>
|
||||||
|
Some(CompoundConstant(MathOperator.NotEqual, c1, c2))
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
}
|
||||||
case _ =>
|
case _ =>
|
||||||
@ -950,14 +955,22 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def evalComparisons(params: List[Expression], vv: Option[Map[String, Constant]], cond: (Long, Long) => Boolean): Option[Constant] = {
|
private def evalComparisons(params: List[Expression], vv: Option[Map[String, Constant]], operator: MathOperator.Value, cond: (Long, Long) => Boolean): Option[Constant] = {
|
||||||
if (params.size < 2) return None
|
if (params.size < 2) return None
|
||||||
val numbers = sequence(params.map{ e =>
|
val paramsEvaluated = params.map { e =>
|
||||||
evalImpl(e, vv) match {
|
evalImpl(e, vv)
|
||||||
|
}
|
||||||
|
val numbers = sequence(paramsEvaluated.map {
|
||||||
case Some(NumericConstant(n, _)) => Some(n)
|
case Some(NumericConstant(n, _)) => Some(n)
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
if (numbers.isEmpty) {
|
||||||
|
paramsEvaluated match {
|
||||||
|
case List(Some(c1), Some(c2)) =>
|
||||||
|
return Some(CompoundConstant(operator, c1, c2))
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
}
|
||||||
numbers.map { ns =>
|
numbers.map { ns =>
|
||||||
if (ns.init.zip(ns.tail).forall(cond.tupled)) Constant.One else Constant.Zero
|
if (ns.init.zip(ns.tail).forall(cond.tupled)) Constant.One else Constant.Zero
|
||||||
}
|
}
|
||||||
|
@ -111,6 +111,8 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
|
|||||||
}
|
}
|
||||||
c match {
|
c match {
|
||||||
case NumericConstant(v, _) => v
|
case NumericConstant(v, _) => v
|
||||||
|
case IfConstant(c, t, f) =>
|
||||||
|
if (deepConstResolve(c) != 0) deepConstResolve(t) else deepConstResolve(f)
|
||||||
case AssertByte(inner) =>
|
case AssertByte(inner) =>
|
||||||
val value = deepConstResolve(inner)
|
val value = deepConstResolve(inner)
|
||||||
if (value.toByte == value) value else {
|
if (value.toByte == value) value else {
|
||||||
@ -184,6 +186,12 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
|
|||||||
case MathOperator.DecimalShl => asDecimal(l, 1 << r, _ * _)
|
case MathOperator.DecimalShl => asDecimal(l, 1 << r, _ * _)
|
||||||
case MathOperator.DecimalShl9 => asDecimal(l, 1 << r, _ * _) & 0x1ff
|
case MathOperator.DecimalShl9 => asDecimal(l, 1 << r, _ * _) & 0x1ff
|
||||||
case MathOperator.DecimalShr => asDecimal(l, 1 << r, _ / _)
|
case MathOperator.DecimalShr => asDecimal(l, 1 << r, _ / _)
|
||||||
|
case MathOperator.Equal => if (l == r) 1 else 0
|
||||||
|
case MathOperator.NotEqual => if (l != r) 1 else 0
|
||||||
|
case MathOperator.Less => if (l < r) 1 else 0
|
||||||
|
case MathOperator.LessEqual => if (l <= r) 1 else 0
|
||||||
|
case MathOperator.Greater => if (l > r) 1 else 0
|
||||||
|
case MathOperator.GreaterEqual => if (l >= r) 1 else 0
|
||||||
case MathOperator.And => l & r
|
case MathOperator.And => l & r
|
||||||
case MathOperator.Exor => l ^ r
|
case MathOperator.Exor => l ^ r
|
||||||
case MathOperator.Or => l | r
|
case MathOperator.Or => l | r
|
||||||
|
Loading…
Reference in New Issue
Block a user