1
0
mirror of https://github.com/KarolS/millfork.git synced 2025-01-01 06:29:53 +00:00

Conversions from bool to byte

This commit is contained in:
Karol Stasiak 2019-11-03 22:26:41 +01:00
parent 590db9ade0
commit 802cd7d86a
6 changed files with 68 additions and 2 deletions

View File

@ -203,7 +203,7 @@ class AbstractExpressionCompiler[T <: AbstractCode] {
failed = true
}
val sourceType = getExpressionType(ctx, params.head)
if (typ.size != sourceType.size && !sourceType.isAssignableTo(typ)) {
if (typ.size != sourceType.size && !sourceType.isExplicitlyCastableTo(typ)) {
ctx.log.error(s"Cannot cast a type ${sourceType.name} to an incompatible type ${typ.name} of different size", params.head.position)
failed = true
}

View File

@ -4,7 +4,7 @@ import millfork.assembly.m6809.{DAccumulatorIndexed, Indexed, MLine, MOpcode, Tw
import millfork.compiler.{AbstractExpressionCompiler, BranchIfFalse, BranchIfTrue, BranchSpec, ComparisonType, CompilationContext, NoBranching}
import millfork.node.{DerefExpression, Expression, FunctionCallExpression, GeneratedConstantExpression, IndexedExpression, LhsExpression, LiteralExpression, M6809Register, SumExpression, VariableExpression}
import millfork.assembly.m6809.MOpcode._
import millfork.env.{AssemblyParamSignature, Constant, ConstantBooleanType, ConstantPointy, ExternFunction, FatBooleanType, FunctionInMemory, FunctionPointerType, M6809RegisterVariable, MacroFunction, MathOperator, MemoryVariable, NonFatalCompilationException, NormalFunction, NormalParamSignature, NumericConstant, StackVariablePointy, ThingInMemory, Type, Variable, VariableInMemory, VariablePointy}
import millfork.env.{AssemblyParamSignature, BuiltInBooleanType, Constant, ConstantBooleanType, ConstantPointy, ExternFunction, FatBooleanType, FlagBooleanType, FunctionInMemory, FunctionPointerType, M6809RegisterVariable, MacroFunction, MathOperator, MemoryVariable, NonFatalCompilationException, NormalFunction, NormalParamSignature, NumericConstant, StackVariablePointy, ThingInMemory, Type, Variable, VariableInMemory, VariablePointy}
import scala.collection.GenTraversableOnce
@ -388,6 +388,9 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
env.maybeGet[Type](fce.functionName) match {
case Some(typ) =>
val sourceType = validateTypeCastAndGetSourceExpressionType(ctx, typ, params)
if (sourceType.isBoollike) {
return compileToFatBooleanInB(ctx, params.head) ++ targetifyB(ctx, target, isSigned = false)
}
return typ.size match {
// TODO: alternating signedness?
case 1 => compileToB(ctx, params.head) ++ targetifyB(ctx, target, isSigned = typ.isSigned)
@ -482,8 +485,35 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
case FatBooleanType => compileToB(ctx, expr)
case t: ConstantBooleanType =>
List(MLine.immediate(MOpcode.LDB, if (t.value) 1 else 0))
case BuiltInBooleanType | _: FlagBooleanType =>
val label = ctx.env.nextLabel("bo")
val condition = compile(ctx, expr, MExpressionTarget.NOTHING, BranchIfFalse(label))
val conditionWithoutJump = condition.init
condition.last.opcode match {
case BCC =>
conditionWithoutJump ++ List(MLine.immediate(LDB, 0), MLine.inherentB(ROL))
case BCS =>
conditionWithoutJump ++ List(MLine.immediate(LDB, 0), MLine.inherentB(ROL), MLine.immediate(EORB, 1))
case BVC | BVS =>
conditionWithoutJump ++ List(
MLine.immediate(LDB, 0),
condition.last,
MLine.inherentB(INC),
MLine.label(label)
)
case _ =>
conditionWithoutJump ++ List(
MLine.immediate(ANDCC, 0xfe),
condition.last,
MLine.immediate(ORCC, 1),
MLine.label(label),
MLine.immediate(LDB, 0),
MLine.inherentB(ROL)
)
}
case _ =>
println(sourceType)
println(expr)
???
}
}

View File

@ -1676,6 +1676,9 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
env.maybeGet[Type](f.functionName) match {
case Some(typ) =>
val sourceType = validateTypeCastAndGetSourceExpressionType(ctx, typ, params)
if (sourceType.isBoollike) {
return compileToFatBooleanInA(ctx, params.head) ++ expressionStorageFromA(ctx, exprTypeAndVariable, position = expr.position, signedSource = false)
}
exprTypeAndVariable match {
case None =>
return compile(ctx, params.head, None, branches)

View File

@ -1202,6 +1202,9 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
env.maybeGet[Type](f.functionName) match {
case Some(typ) =>
val sourceType = validateTypeCastAndGetSourceExpressionType(ctx, typ, params)
if (sourceType.isBoollike) {
return targetifyA(ctx, target, compileToFatBooleanInA(ctx, params.head), isSigned = false)
}
return typ.size match {
// TODO: alternating signedness?
case 1 => targetifyA(ctx, target, compileToA(ctx, params.head), isSigned = typ.isSigned)

View File

@ -23,12 +23,16 @@ sealed trait Type extends CallableThing {
def isSigned: Boolean
def isBoollike: Boolean = false
def isSubtypeOf(other: Type): Boolean = this == other
def isCompatible(other: Type): Boolean = this == other
override def toString: String = name
def isExplicitlyCastableTo(targetType: Type): Boolean = isAssignableTo(targetType)
def isAssignableTo(targetType: Type): Boolean = isCompatible(targetType)
def isArithmetic = false
@ -131,6 +135,8 @@ case object FatBooleanType extends VariableType {
override def isSigned: Boolean = false
override def isBoollike: Boolean = true
override def name: String = "bool"
override def isPointy: Boolean = false
@ -138,6 +144,8 @@ case object FatBooleanType extends VariableType {
override def isSubtypeOf(other: Type): Boolean = this == other
override def isAssignableTo(targetType: Type): Boolean = this == targetType
override def isExplicitlyCastableTo(targetType: Type): Boolean = targetType.isArithmetic || isAssignableTo(targetType)
}
sealed trait BooleanType extends Type {
@ -145,7 +153,11 @@ sealed trait BooleanType extends Type {
def isSigned = false
override def isBoollike: Boolean = true
override def isAssignableTo(targetType: Type): Boolean = isCompatible(targetType) || targetType == FatBooleanType
override def isExplicitlyCastableTo(targetType: Type): Boolean = targetType.isArithmetic || isAssignableTo(targetType)
}
case class ConstantBooleanType(name: String, value: Boolean) extends BooleanType

View File

@ -246,4 +246,22 @@ class BooleanSuite extends FunSuite with Matchers {
m.readByte(0xc001) should equal(1)
}
}
test("Boolean to number conversions") {
val code =
"""
|byte output @$c000
|void main () {
|output = 0
|output += byte(output == 0) //
|output += byte(output == 0)
|output += byte(output != 2) //
|output += byte(output != 2)
|output += byte(2 > 1) //
|}
|""".stripMargin
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)(code){ m =>
m.readByte(0xc000) should equal(code.count(_ == '↑'))
}
}
}