1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-17 11:28:55 +00:00

Multiple arguments for some relative operators

This commit is contained in:
Karol Stasiak 2018-01-01 22:37:23 +01:00
parent 3e0d1d4978
commit 504cb56ee7
2 changed files with 81 additions and 25 deletions

View File

@ -405,15 +405,12 @@ object MlCompiler {
}
}
def assertComparison(ctx: CompilationContext, params: List[Expression]): (Expression, Expression, Int, Boolean) = {
if (params.length != 2) {
ErrorReporting.fatal("sfgdgfsd", None)
}
def assertComparison(ctx: CompilationContext, params: List[Expression]): (Int, Boolean) = {
(params.head, params(1)) match {
case (l: Expression, r: Expression) =>
val lt = getExpressionType(ctx, l)
val rt = getExpressionType(ctx, r)
(l, r, lt.size max rt.size, lt.isSigned || rt.isSigned)
(lt.size max rt.size, lt.isSigned || rt.isSigned)
}
}
@ -902,37 +899,47 @@ object MlCompiler {
DecimalBuiltIns.compileByteShiftRight(ctx, l, r, rotate = false)
case "<" =>
// TODO: signed
val (l, r, size, signed) = assertComparison(ctx, params)
size match {
case 1 => BuiltIns.compileByteComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
case 2 => BuiltIns.compileWordComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
val (size, signed) = assertComparison(ctx, params)
compileTransitiveRelation(ctx, "<", params, exprTypeAndVariable, branches) { (l, r) =>
size match {
case 1 => BuiltIns.compileByteComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
case 2 => BuiltIns.compileWordComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
}
}
case ">=" =>
// TODO: signed
val (l, r, size, signed) = assertComparison(ctx, params)
size match {
case 1 => BuiltIns.compileByteComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
case 2 => BuiltIns.compileWordComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
val (size, signed) = assertComparison(ctx, params)
compileTransitiveRelation(ctx, ">=", params, exprTypeAndVariable, branches) { (l, r) =>
size match {
case 1 => BuiltIns.compileByteComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
case 2 => BuiltIns.compileWordComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
}
}
case ">" =>
// TODO: signed
val (l, r, size, signed) = assertComparison(ctx, params)
size match {
case 1 => BuiltIns.compileByteComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
case 2 => BuiltIns.compileWordComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
val (size, signed) = assertComparison(ctx, params)
compileTransitiveRelation(ctx, ">", params, exprTypeAndVariable, branches) { (l, r) =>
size match {
case 1 => BuiltIns.compileByteComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
case 2 => BuiltIns.compileWordComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
}
}
case "<=" =>
// TODO: signed
val (l, r, size, signed) = assertComparison(ctx, params)
size match {
case 1 => BuiltIns.compileByteComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
case 2 => BuiltIns.compileWordComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
val (size, signed) = assertComparison(ctx, params)
compileTransitiveRelation(ctx, "<=", params, exprTypeAndVariable, branches) { (l, r) =>
size match {
case 1 => BuiltIns.compileByteComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
case 2 => BuiltIns.compileWordComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
}
}
case "==" =>
val (l, r, size) = assertBinary(ctx, params)
size match {
case 1 => BuiltIns.compileByteComparison(ctx, ComparisonType.Equal, l, r, branches)
case 2 => BuiltIns.compileWordComparison(ctx, ComparisonType.Equal, l, r, branches)
val size = params.map(p => getExpressionType(ctx, p).size).max
compileTransitiveRelation(ctx, "==", params, exprTypeAndVariable, branches) { (l, r) =>
size match {
case 1 => BuiltIns.compileByteComparison(ctx, ComparisonType.Equal, l, r, branches)
case 2 => BuiltIns.compileWordComparison(ctx, ComparisonType.Equal, l, r, branches)
}
}
case "!=" =>
val (l, r, size) = assertBinary(ctx, params)
@ -1138,6 +1145,23 @@ object MlCompiler {
}
}
private def compileTransitiveRelation(ctx: CompilationContext,
operator: String,
params: List[Expression],
exprTypeAndVariable: Option[(Type, Variable)],
branches: BranchSpec)(binary: (Expression, Expression) => List[AssemblyLine]): List[AssemblyLine] ={
params match {
case List(l, r) => binary(l, r)
case List(_) | Nil =>
ErrorReporting.fatal("")
case _ =>
val conjunction = params.init.zip(params.tail).map {
case (l, r) => FunctionCallExpression(operator, List(l, r))
}.reduceLeft((a,b) => FunctionCallExpression("&&", List(a, b)))
compile(ctx, conjunction, exprTypeAndVariable, branches)
}
}
def expressionStorageFromAX(ctx: CompilationContext, exprTypeAndVariable: Option[(Type, Variable)], position: Option[Position]): List[AssemblyLine] = {
exprTypeAndVariable.fold(noop) {
case (VoidType, _) => ???

View File

@ -261,4 +261,36 @@ class ComparisonSuite extends FunSuite with Matchers {
""".stripMargin
EmuBenchmarkRun(src)(_.readWord(0xc000) should equal(src.count(_ == '+')))
}
test("Multiple params for equality") {
EmuBenchmarkRun(
"""
| byte output @$c000
| void main () {
| output = 5
| if (output == 5 == 5) {
| output += 1
| }
| if (output == 5 == 6) {
| output += 78
| }
| }
""".stripMargin)(_.readWord(0xc000) should equal(6))
}
test("Multiple params for inequality") {
EmuBenchmarkRun(
"""
| byte output @$c000
| void main () {
| output = 5
| if 2 < 3 < 4 {
| output += 1
| }
| if 2 < 3 < 2 {
| output += 78
| }
| }
""".stripMargin)(_.readWord(0xc000) should equal(6))
}
}