From 92eb3b0bf6c7d52a1ef3b3843cdf107f16ae4bb5 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 9 Jul 2022 22:29:38 +0200 Subject: [PATCH] bool logical testcase --- compiler/test/TestTypecasts.kt | 426 ++++++++++++++++++ .../prog8/ast/expressions/AstExpressions.kt | 10 + docs/source/todo.rst | 2 + 3 files changed, 438 insertions(+) diff --git a/compiler/test/TestTypecasts.kt b/compiler/test/TestTypecasts.kt index 3ca992944..9d861844e 100644 --- a/compiler/test/TestTypecasts.kt +++ b/compiler/test/TestTypecasts.kt @@ -20,6 +20,432 @@ import prog8tests.helpers.compileText class TestTypecasts: FunSpec({ + test("logical with byte instead of bool") { + val text=""" +%import textio + +main { + + sub ftrue(ubyte arg) -> ubyte { + arg++ + return 128 + } + + sub ffalse(ubyte arg) -> ubyte { + arg++ + return 0 + } + + sub start() { + ubyte ub1 = 2 + ubyte ub2 = 4 + ubyte ub3 = 8 + ubyte ub4 = 0 + ubyte bvalue + + txt.print("const not 0: ") + txt.print_ub(not 129) + txt.nl() + txt.print("const not 1: ") + txt.print_ub(not 0) + txt.nl() + txt.print("const inv 126: ") + txt.print_ub(~ 129) + txt.nl() + txt.print("const inv 255: ") + txt.print_ub(~ 0) + txt.nl() + bvalue = 129 + txt.print("bitwise inv 126: ") + bvalue = ~ bvalue + txt.print_ub(bvalue) + txt.nl() + bvalue = 0 + txt.print("bitwise inv 255: ") + bvalue = ~ bvalue + txt.print_ub(bvalue) + txt.nl() + + txt.print("bitwise or 14: ") + txt.print_ub(ub1 | ub2 | ub3 | ub4) + txt.nl() + txt.print("bitwise or 142: ") + txt.print_ub(ub1 | ub2 | ub3 | ub4 | 128) + txt.nl() + txt.print("bitwise and 0: ") + txt.print_ub(ub1 & ub2 & ub3 & ub4) + txt.nl() + txt.print("bitwise and 8: ") + txt.print_ub(ub3 & ub3 & 127) + txt.nl() + txt.print("bitwise xor 14: ") + txt.print_ub(ub1 ^ ub2 ^ ub3 ^ ub4) + txt.nl() + txt.print("bitwise xor 6: ") + txt.print_ub(ub1 ^ ub2 ^ ub3 ^ 8) + txt.nl() + txt.print("bitwise not 247: ") + txt.print_ub(~ub3) + txt.nl() + txt.print("bitwise not 255: ") + txt.print_ub(~ub4) + txt.nl() + + txt.print("not 0: ") + bvalue = 3 * (ub4 | not (ub3 | ub3 | ub3)) + txt.print_ub(bvalue) + if 3*(ub4 | not (ub1 | ub1 | ub1)) + txt.print(" / fail") + else + txt.print(" / ok") + txt.nl() + + txt.print("not 0: ") + bvalue = not ub3 + txt.print_ub(bvalue) + if not ub1 + txt.print(" / fail") + else + txt.print(" / ok") + txt.nl() + + txt.print("not 1: ") + bvalue = not ub4 + txt.print_ub(bvalue) + if not ub4 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + + bvalue = bvalue and 128 + txt.print("bvl 1: ") + txt.print_ub(bvalue) + if bvalue and 128 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + + txt.print("and 1: ") + bvalue = ub1 and ub2 and ub3 + txt.print_ub(bvalue) + if ub1 and ub2 and ub3 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print("and 1: ") + bvalue = ub1 and ub2 and ub3 and 64 + txt.print_ub(bvalue) + if ub1 and ub2 and ub3 and 64 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print("and 1: ") + bvalue = ub1 and ub2 and ub3 and ftrue(99) + txt.print_ub(bvalue) + if ub1 and ub2 and ub3 and ftrue(99) + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print("and 0: ") + bvalue = ub1 and ub2 and ub3 and ub4 + txt.print_ub(bvalue) + if ub1 and ub2 and ub3 and ub4 + txt.print(" / fail") + else + txt.print(" / ok") + txt.nl() + txt.print("and 0: ") + bvalue = ub1 and ub2 and ub3 and ffalse(99) + txt.print_ub(bvalue) + if ub1 and ub2 and ub3 and ffalse(99) + txt.print(" / fail") + else + txt.print(" / ok") + txt.nl() + + txt.print(" or 1: ") + bvalue = ub1 or ub2 or ub3 or ub4 + txt.print_ub(bvalue) + if ub1 or ub2 or ub3 or ub4 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print(" or 1: ") + bvalue = ub4 or ub4 or ub1 + txt.print_ub(bvalue) + if ub4 or ub4 or ub1 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print(" or 1: ") + bvalue = ub1 or ub2 or ub3 or ftrue(99) + txt.print_ub(bvalue) + if ub1 or ub2 or ub3 or ftrue(99) + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + + txt.print("xor 1: ") + bvalue = ub1 xor ub2 xor ub3 xor ub4 + txt.print_ub(bvalue) + if ub1 xor ub2 xor ub3 xor ub4 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print("xor 1: ") + bvalue = ub1 xor ub2 xor ub3 xor ffalse(99) + txt.print_ub(bvalue) + if ub1 xor ub2 xor ub3 xor ffalse(99) + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + + txt.print("xor 0: ") + bvalue = ub1 xor ub2 xor ub3 xor ub4 xor true + txt.print_ub(bvalue) + if ub1 xor ub2 xor ub3 xor ub4 xor true + txt.print(" / fail") + else + txt.print(" / ok") + txt.nl() + txt.print("xor 0: ") + bvalue = ub1 xor ub2 xor ub3 xor ftrue(99) + txt.print_ub(bvalue) + if ub1 xor ub2 xor ub3 xor ftrue(99) + txt.print(" / fail") + else + txt.print(" / ok") + } +} + """ + val result = compileText(C64Target(), true, text, writeAssembly = true)!! + val stmts = result.program.entrypoint.statements + stmts.size shouldBeGreaterThan 10 + } + + test("logical with bools") { + val text=""" +%import textio + +main { + + sub ftrue(ubyte arg) -> ubyte { + arg++ + return 128 + } + + sub ffalse(ubyte arg) -> ubyte { + arg++ + return 0 + } + + sub start() { + bool ub1 = 2 + bool ub2 = 4 + bool ub3 = 8 + bool ub4 = 0 + bool bvalue + + txt.print("const not 0: ") + txt.print_ub(not 129) + txt.nl() + txt.print("const not 1: ") + txt.print_ub(not 0) + txt.nl() + txt.print("const inv 126: ") + txt.print_ub(~ 129) + txt.nl() + txt.print("const inv 255: ") + txt.print_ub(~ 0) + txt.nl() + bvalue = 129 + txt.print("bitwise inv 126: ") + bvalue = ~ bvalue + txt.print_ub(bvalue) + txt.nl() + bvalue = 0 + txt.print("bitwise inv 255: ") + bvalue = ~ bvalue + txt.print_ub(bvalue) + txt.nl() + + txt.print("bitwise or 14: ") + txt.print_ub(ub1 | ub2 | ub3 | ub4) + txt.nl() + txt.print("bitwise or 142: ") + txt.print_ub(ub1 | ub2 | ub3 | ub4 | 128) + txt.nl() + txt.print("bitwise and 0: ") + txt.print_ub(ub1 & ub2 & ub3 & ub4) + txt.nl() + txt.print("bitwise and 8: ") + txt.print_ub(ub3 & ub3 & 127) + txt.nl() + txt.print("bitwise xor 14: ") + txt.print_ub(ub1 ^ ub2 ^ ub3 ^ ub4) + txt.nl() + txt.print("bitwise xor 6: ") + txt.print_ub(ub1 ^ ub2 ^ ub3 ^ 8) + txt.nl() + txt.print("bitwise not 247: ") + txt.print_ub(~ub3) + txt.nl() + txt.print("bitwise not 255: ") + txt.print_ub(~ub4) + txt.nl() + + txt.print("not 0: ") + bvalue = 3 * (ub4 | not (ub3 | ub3 | ub3)) + txt.print_ub(bvalue) + if 3*(ub4 | not (ub1 | ub1 | ub1)) + txt.print(" / fail") + else + txt.print(" / ok") + txt.nl() + + txt.print("not 0: ") + bvalue = not ub3 + txt.print_ub(bvalue) + if not ub1 + txt.print(" / fail") + else + txt.print(" / ok") + txt.nl() + + txt.print("not 1: ") + bvalue = not ub4 + txt.print_ub(bvalue) + if not ub4 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + + bvalue = bvalue and 128 + txt.print("bvl 1: ") + txt.print_ub(bvalue) + if bvalue and 128 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + + txt.print("and 1: ") + bvalue = ub1 and ub2 and ub3 + txt.print_ub(bvalue) + if ub1 and ub2 and ub3 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print("and 1: ") + bvalue = ub1 and ub2 and ub3 and 64 + txt.print_ub(bvalue) + if ub1 and ub2 and ub3 and 64 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print("and 1: ") + bvalue = ub1 and ub2 and ub3 and ftrue(99) + txt.print_ub(bvalue) + if ub1 and ub2 and ub3 and ftrue(99) + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print("and 0: ") + bvalue = ub1 and ub2 and ub3 and ub4 + txt.print_ub(bvalue) + if ub1 and ub2 and ub3 and ub4 + txt.print(" / fail") + else + txt.print(" / ok") + txt.nl() + txt.print("and 0: ") + bvalue = ub1 and ub2 and ub3 and ffalse(99) + txt.print_ub(bvalue) + if ub1 and ub2 and ub3 and ffalse(99) + txt.print(" / fail") + else + txt.print(" / ok") + txt.nl() + + txt.print(" or 1: ") + bvalue = ub1 or ub2 or ub3 or ub4 + txt.print_ub(bvalue) + if ub1 or ub2 or ub3 or ub4 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print(" or 1: ") + bvalue = ub4 or ub4 or ub1 + txt.print_ub(bvalue) + if ub4 or ub4 or ub1 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print(" or 1: ") + bvalue = ub1 or ub2 or ub3 or ftrue(99) + txt.print_ub(bvalue) + if ub1 or ub2 or ub3 or ftrue(99) + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + + txt.print("xor 1: ") + bvalue = ub1 xor ub2 xor ub3 xor ub4 + txt.print_ub(bvalue) + if ub1 xor ub2 xor ub3 xor ub4 + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + txt.print("xor 1: ") + bvalue = ub1 xor ub2 xor ub3 xor ffalse(99) + txt.print_ub(bvalue) + if ub1 xor ub2 xor ub3 xor ffalse(99) + txt.print(" / ok") + else + txt.print(" / fail") + txt.nl() + + txt.print("xor 0: ") + bvalue = ub1 xor ub2 xor ub3 xor ub4 xor true + txt.print_ub(bvalue) + if ub1 xor ub2 xor ub3 xor ub4 xor true + txt.print(" / fail") + else + txt.print(" / ok") + txt.nl() + txt.print("xor 0: ") + bvalue = ub1 xor ub2 xor ub3 xor ftrue(99) + txt.print_ub(bvalue) + if ub1 xor ub2 xor ub3 xor ftrue(99) + txt.print(" / fail") + else + txt.print(" / ok") + } +} + """ + val result = compileText(C64Target(), true, text, writeAssembly = true)!! + val stmts = result.program.entrypoint.statements + stmts.size shouldBeGreaterThan 10 + } + test("bool arrays") { val text=""" main { diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index a01496614..cf639f4ff 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -185,6 +185,16 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex val leftDt = left.inferType(program) val rightDt = right.inferType(program) +// fun dynamicBooleanType(): InferredTypes.InferredType { +// // as a special case, an expression yielding a boolean result, adapts the result +// // type to what is required (byte or word), to avoid useless type casting +// return when (parent) { +// is TypecastExpression -> InferredTypes.InferredType.known((parent as TypecastExpression).type) +// is Assignment -> (parent as Assignment).target.inferType(program) +// else -> InferredTypes.InferredType.known(DataType.BOOL) // or UBYTE? +// } +// } + return when (operator) { "+", "-", "*", "%", "/" -> { if (!leftDt.isKnown || !rightDt.isKnown) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 1a6588fb3..3876f0362 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,6 +3,8 @@ TODO For next release ^^^^^^^^^^^^^^^^ +- fix code gen crashes in logical.p8 / testtypecasts + - have a proper option to move the evalstack rather than just assembly symbol redefine - then make the cx16 virtual registers in syslib.p8 use that definition to be able to shift them around on non-cx16 targets