From 078485134dd07643b737c3c8b2ec6cb0975ee82b Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 1 Jun 2021 21:21:33 +0200 Subject: [PATCH] split up unittests files --- compiler/test/AsmgenTests.kt | 122 ++++ compiler/test/TestMemory.kt | 192 ++++++ compiler/test/TestNumbers.kt | 116 ++++ ...ts.kt => TestParserNumericLiteralValue.kt} | 8 +- compiler/test/TestPetscii.kt | 108 +++ compiler/test/UnitTests.kt | 649 ------------------ compiler/test/ZeropageTests.kt | 265 +++++++ 7 files changed, 807 insertions(+), 653 deletions(-) create mode 100644 compiler/test/AsmgenTests.kt create mode 100644 compiler/test/TestMemory.kt create mode 100644 compiler/test/TestNumbers.kt rename compiler/test/{LiteralValueTests.kt => TestParserNumericLiteralValue.kt} (98%) create mode 100644 compiler/test/TestPetscii.kt delete mode 100644 compiler/test/UnitTests.kt create mode 100644 compiler/test/ZeropageTests.kt diff --git a/compiler/test/AsmgenTests.kt b/compiler/test/AsmgenTests.kt new file mode 100644 index 000000000..9c3576e32 --- /dev/null +++ b/compiler/test/AsmgenTests.kt @@ -0,0 +1,122 @@ +package prog8tests + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.TestInstance +import prog8.ast.IBuiltinFunctions +import prog8.ast.IMemSizer +import prog8.ast.Module +import prog8.ast.Program +import prog8.ast.base.* +import prog8.ast.expressions.* +import prog8.ast.statements.* +import prog8.compiler.* +import prog8.compiler.target.C64Target +import prog8.compiler.target.c64.C64MachineDefinition +import prog8.compiler.target.cpu6502.codegen.AsmGen +import java.nio.file.Path + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class TestAsmGen6502 { + private class DummyFunctions: IBuiltinFunctions { + override val names: Set = emptySet() + override val purefunctionNames: Set = emptySet() + override fun constValue(name: String, args: List, position: Position, memsizer: IMemSizer): NumericLiteralValue? = null + override fun returnType(name: String, args: MutableList) = InferredTypes.InferredType.unknown() + } + + private class DummyMemsizer: IMemSizer { + override fun memorySize(dt: DataType): Int = 0 + } + + private fun createTestProgram(): Program { + /* +block1 { + + sub test () { + uword var_in_sub = 1234 + uword var2_in_sub + +label_in_sub: + var2_in_sub = var_in_sub + var2_in_sub = &label_in_sub + } +} + + */ + val varInSub = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "var_in_sub", NumericLiteralValue.optimalInteger(1234, Position.DUMMY), false, false, false, Position.DUMMY) + val var2InSub = VarDecl(VarDeclType.VAR, DataType.UWORD, ZeropageWish.DONTCARE, null, "var2_in_sub", null, false, false, false, Position.DUMMY) + val labelInSub = Label("label_in_sub", Position.DUMMY) + + val tgt = AssignTarget(IdentifierReference(listOf("var2_in_sub"), Position.DUMMY), null, null, Position.DUMMY) + val assign1 = Assignment(tgt, IdentifierReference(listOf("var_in_sub"), Position.DUMMY), Position.DUMMY) + val assign2 = Assignment(tgt, AddressOf(IdentifierReference(listOf("label_in_sub"), Position.DUMMY), Position.DUMMY), Position.DUMMY) + + val statements = mutableListOf(varInSub, var2InSub, labelInSub, assign1, assign2) + val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, statements, Position.DUMMY) + val block1 = Block("block1", null, mutableListOf(subroutine), false, Position.DUMMY) + + val block2 = Block("block2", null, mutableListOf(), false, Position.DUMMY) + + val module = Module("test", mutableListOf(block1, block2), Position.DUMMY, false, Path.of("")) + module.linkParents(ParentSentinel) + val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) + return program + } + + private fun createTestAsmGen(program: Program): AsmGen { + val errors = ErrorReporter() + val options = CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, true, C64Target) + val zp = C64MachineDefinition.C64Zeropage(options) + val asmgen = AsmGen(program, errors, zp, options, C64Target, Path.of(".")) + return asmgen + } + + @Test + fun testSymbolNameFromStrings() { + val program = createTestProgram() + val asmgen = createTestAsmGen(program) + + printAst(program) // TODO weg + + assertThat(asmgen.asmSymbolName("name"), equalTo("name")) + assertThat(asmgen.asmSymbolName(""), equalTo("prog8_name")) + assertThat(asmgen.asmSymbolName(RegisterOrPair.R15), equalTo("cx16.r15")) + assertThat(asmgen.asmSymbolName(listOf("a", "b", "name")), equalTo("a.b.name")) + assertThat(asmgen.asmVariableName("name"), equalTo("name")) + assertThat(asmgen.asmVariableName(""), equalTo("prog8_name")) + assertThat(asmgen.asmVariableName(listOf("a", "b", "name")), equalTo("a.b.name")) + } + + @Test + @Disabled("TODO") // TODO + fun testSymbolNameFromVarIdentifier() { + val program = createTestProgram() + val asmgen = createTestAsmGen(program) + + val varIdent = IdentifierReference(listOf("variable"), Position.DUMMY) + assertThat(asmgen.asmSymbolName(varIdent), equalTo("variable")) + assertThat(asmgen.asmVariableName(varIdent), equalTo("variable")) + + val scopedVarIdent = IdentifierReference(listOf("scope", "variable"), Position.DUMMY) + assertThat(asmgen.asmSymbolName(scopedVarIdent), equalTo("scope.variable")) + assertThat(asmgen.asmVariableName(scopedVarIdent), equalTo("scope.variable")) + } + + @Test + @Disabled("TODO") // TODO + fun testSymbolNameFromLabelIdentifier() { + val program = createTestProgram() + val asmgen = createTestAsmGen(program) + + val labelIdent = IdentifierReference(listOf("label"), Position.DUMMY) + assertThat(asmgen.asmSymbolName(labelIdent), equalTo("_label")) + assertThat(asmgen.asmVariableName(labelIdent), equalTo("_label")) + + val scopedLabelIdent = IdentifierReference(listOf("scope", "label"), Position.DUMMY) + assertThat(asmgen.asmSymbolName(scopedLabelIdent), equalTo("scope._label")) + assertThat(asmgen.asmVariableName(scopedLabelIdent), equalTo("scope._label")) + } +} diff --git a/compiler/test/TestMemory.kt b/compiler/test/TestMemory.kt new file mode 100644 index 000000000..0c266848a --- /dev/null +++ b/compiler/test/TestMemory.kt @@ -0,0 +1,192 @@ +package prog8tests + +import org.junit.jupiter.api.Test +import prog8.ast.IBuiltinFunctions +import prog8.ast.IMemSizer +import prog8.ast.Module +import prog8.ast.Program +import prog8.ast.base.DataType +import prog8.ast.base.ParentSentinel +import prog8.ast.base.Position +import prog8.ast.base.VarDeclType +import prog8.ast.expressions.* +import prog8.ast.statements.* +import prog8.compiler.target.C64Target +import java.nio.file.Path +import kotlin.test.assertFalse +import kotlin.test.assertTrue + + +class TestMemory { + private class DummyFunctions: IBuiltinFunctions { + override val names: Set = emptySet() + override val purefunctionNames: Set = emptySet() + override fun constValue(name: String, args: List, position: Position, memsizer: IMemSizer): NumericLiteralValue? = null + override fun returnType(name: String, args: MutableList) = InferredTypes.InferredType.unknown() + } + + private class DummyMemsizer: IMemSizer { + override fun memorySize(dt: DataType): Int = 0 + } + + @Test + fun testInValidRamC64_memory_addresses() { + + var memexpr = NumericLiteralValue.optimalInteger(0x0000, Position.DUMMY) + var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + val program = Program("test", mutableListOf(), DummyFunctions(), DummyMemsizer()) + assertTrue(C64Target.isInRegularRAM(target, program)) + + memexpr = NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assertTrue(C64Target.isInRegularRAM(target, program)) + + memexpr = NumericLiteralValue.optimalInteger(0x9fff, Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assertTrue(C64Target.isInRegularRAM(target, program)) + + memexpr = NumericLiteralValue.optimalInteger(0xc000, Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assertTrue(C64Target.isInRegularRAM(target, program)) + + memexpr = NumericLiteralValue.optimalInteger(0xcfff, Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assertTrue(C64Target.isInRegularRAM(target, program)) + } + + @Test + fun testNotInValidRamC64_memory_addresses() { + + var memexpr = NumericLiteralValue.optimalInteger(0xa000, Position.DUMMY) + var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + val program = Program("test", mutableListOf(), DummyFunctions(), DummyMemsizer()) + assertFalse(C64Target.isInRegularRAM(target, program)) + + memexpr = NumericLiteralValue.optimalInteger(0xafff, Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assertFalse(C64Target.isInRegularRAM(target, program)) + + memexpr = NumericLiteralValue.optimalInteger(0xd000, Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assertFalse(C64Target.isInRegularRAM(target, program)) + + memexpr = NumericLiteralValue.optimalInteger(0xffff, Position.DUMMY) + target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + assertFalse(C64Target.isInRegularRAM(target, program)) + } + + @Test + fun testInValidRamC64_memory_identifiers() { + var target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.VAR) + val program = Program("test", mutableListOf(), DummyFunctions(), DummyMemsizer()) + + assertTrue(C64Target.isInRegularRAM(target, program)) + target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.VAR) + assertFalse(C64Target.isInRegularRAM(target, program)) + target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.CONST) + assertTrue(C64Target.isInRegularRAM(target, program)) + target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.CONST) + assertFalse(C64Target.isInRegularRAM(target, program)) + target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.MEMORY) + assertFalse(C64Target.isInRegularRAM(target, program)) + } + + @Test + private fun createTestProgramForMemoryRefViaVar(address: Int, vartype: VarDeclType): AssignTarget { + val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val memexpr = IdentifierReference(listOf("address"), Position.DUMMY) + val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) + val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) + module.linkParents(ParentSentinel) + return target + } + + @Test + fun testInValidRamC64_memory_expression() { + val memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY), Position.DUMMY) + val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) + val program = Program("test", mutableListOf(), DummyFunctions(), DummyMemsizer()) + assertFalse(C64Target.isInRegularRAM(target, program)) + } + + @Test + fun testInValidRamC64_variable() { + val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY) + val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) + val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) + val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) + val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) + module.linkParents(ParentSentinel) + assertTrue(C64Target.isInRegularRAM(target, program)) + } + + @Test + fun testInValidRamC64_memmap_variable() { + val address = 0x1000 + val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) + val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) + val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) + val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) + module.linkParents(ParentSentinel) + assertTrue(C64Target.isInRegularRAM(target, program)) + } + + @Test + fun testNotInValidRamC64_memmap_variable() { + val address = 0xd020 + val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) + val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) + val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) + val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) + module.linkParents(ParentSentinel) + assertFalse(C64Target.isInRegularRAM(target, program)) + } + + @Test + fun testInValidRamC64_array() { + val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY) + val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) + val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) + val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) + val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) + val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) + module.linkParents(ParentSentinel) + assertTrue(C64Target.isInRegularRAM(target, program)) + } + + @Test + fun testInValidRamC64_array_memmapped() { + val address = 0x1000 + val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) + val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) + val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) + val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) + val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) + module.linkParents(ParentSentinel) + assertTrue(C64Target.isInRegularRAM(target, program)) + } + + @Test + fun testNotValidRamC64_array_memmapped() { + val address = 0xe000 + val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) + val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) + val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) + val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) + val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) + val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) + val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) + module.linkParents(ParentSentinel) + assertFalse(C64Target.isInRegularRAM(target, program)) + } +} diff --git a/compiler/test/TestNumbers.kt b/compiler/test/TestNumbers.kt new file mode 100644 index 000000000..1de09e330 --- /dev/null +++ b/compiler/test/TestNumbers.kt @@ -0,0 +1,116 @@ +package prog8tests + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.closeTo +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import prog8.ast.toHex +import prog8.compiler.CompilerException +import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_NEGATIVE +import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_POSITIVE +import prog8.compiler.target.c64.C64MachineDefinition.Mflpt5 +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class TestNumbers { + @Test + fun testToHex() { + assertEquals("0", 0.toHex()) + assertEquals("1", 1.toHex()) + assertEquals("1", 1.234.toHex()) + assertEquals("10", 10.toHex()) + assertEquals("10", 10.99.toHex()) + assertEquals("15", 15.toHex()) + assertEquals("\$10", 16.toHex()) + assertEquals("\$ff", 255.toHex()) + assertEquals("\$0100", 256.toHex()) + assertEquals("\$4e5c", 20060.toHex()) + assertEquals("\$c382", 50050.toHex()) + assertEquals("\$ffff", 65535.toHex()) + assertEquals("\$ffff", 65535L.toHex()) + assertEquals("0", 0.toHex()) + assertEquals("-1", (-1).toHex()) + assertEquals("-1", (-1.234).toHex()) + assertEquals("-10", (-10).toHex()) + assertEquals("-10", (-10.99).toHex()) + assertEquals("-15", (-15).toHex()) + assertEquals("-\$10", (-16).toHex()) + assertEquals("-\$ff", (-255).toHex()) + assertEquals("-\$0100", (-256).toHex()) + assertEquals("-\$4e5c", (-20060).toHex()) + assertEquals("-\$c382", (-50050).toHex()) + assertEquals("-\$ffff", (-65535).toHex()) + assertEquals("-\$ffff", (-65535L).toHex()) + assertFailsWith { 65536.toHex() } + assertFailsWith { 65536L.toHex() } + } + + @Test + fun testFloatToMflpt5() { + assertThat(Mflpt5.fromNumber(0), equalTo(Mflpt5(0x00, 0x00, 0x00, 0x00, 0x00))) + assertThat(Mflpt5.fromNumber(3.141592653), equalTo(Mflpt5(0x82, 0x49, 0x0F, 0xDA, 0xA1))) + assertThat(Mflpt5.fromNumber(3.141592653589793), equalTo(Mflpt5(0x82, 0x49, 0x0F, 0xDA, 0xA2))) + assertThat(Mflpt5.fromNumber(32768), equalTo(Mflpt5(0x90, 0x00, 0x00, 0x00, 0x00))) + assertThat(Mflpt5.fromNumber(-32768), equalTo(Mflpt5(0x90, 0x80, 0x00, 0x00, 0x00))) + assertThat(Mflpt5.fromNumber(1), equalTo(Mflpt5(0x81, 0x00, 0x00, 0x00, 0x00))) + assertThat(Mflpt5.fromNumber(0.7071067812), equalTo(Mflpt5(0x80, 0x35, 0x04, 0xF3, 0x34))) + assertThat(Mflpt5.fromNumber(0.7071067811865476), equalTo(Mflpt5(0x80, 0x35, 0x04, 0xF3, 0x33))) + assertThat(Mflpt5.fromNumber(1.4142135624), equalTo(Mflpt5(0x81, 0x35, 0x04, 0xF3, 0x34))) + assertThat(Mflpt5.fromNumber(1.4142135623730951), equalTo(Mflpt5(0x81, 0x35, 0x04, 0xF3, 0x33))) + assertThat(Mflpt5.fromNumber(-.5), equalTo(Mflpt5(0x80, 0x80, 0x00, 0x00, 0x00))) + assertThat(Mflpt5.fromNumber(0.69314718061), equalTo(Mflpt5(0x80, 0x31, 0x72, 0x17, 0xF8))) + assertThat(Mflpt5.fromNumber(0.6931471805599453), equalTo(Mflpt5(0x80, 0x31, 0x72, 0x17, 0xF7))) + assertThat(Mflpt5.fromNumber(10), equalTo(Mflpt5(0x84, 0x20, 0x00, 0x00, 0x00))) + assertThat(Mflpt5.fromNumber(1000000000), equalTo(Mflpt5(0x9E, 0x6E, 0x6B, 0x28, 0x00))) + assertThat(Mflpt5.fromNumber(.5), equalTo(Mflpt5(0x80, 0x00, 0x00, 0x00, 0x00))) + assertThat(Mflpt5.fromNumber(1.4426950408889634), equalTo(Mflpt5(0x81, 0x38, 0xAA, 0x3B, 0x29))) + assertThat(Mflpt5.fromNumber(1.5707963267948966), equalTo(Mflpt5(0x81, 0x49, 0x0F, 0xDA, 0xA2))) + assertThat(Mflpt5.fromNumber(6.283185307179586), equalTo(Mflpt5(0x83, 0x49, 0x0F, 0xDA, 0xA2))) + assertThat(Mflpt5.fromNumber(.25), equalTo(Mflpt5(0x7F, 0x00, 0x00, 0x00, 0x00))) + assertThat(Mflpt5.fromNumber(123.45678e22), equalTo(Mflpt5(0xd1, 0x02, 0xb7, 0x06, 0xfb))) + assertThat(Mflpt5.fromNumber(-123.45678e-22), equalTo(Mflpt5(0x3e, 0xe9, 0x34, 0x09, 0x1b))) + } + + @Test + fun testFloatRange() { + assertThat(Mflpt5.fromNumber(FLOAT_MAX_POSITIVE), equalTo(Mflpt5(0xff, 0x7f, 0xff, 0xff, 0xff))) + assertThat(Mflpt5.fromNumber(FLOAT_MAX_NEGATIVE), equalTo(Mflpt5(0xff, 0xff, 0xff, 0xff, 0xff))) + assertThat(Mflpt5.fromNumber(1.7e-38), equalTo(Mflpt5(0x03, 0x39, 0x1d, 0x15, 0x63))) + assertThat(Mflpt5.fromNumber(1.7e-39), equalTo(Mflpt5(0x00, 0x00, 0x00, 0x00, 0x00))) + assertThat(Mflpt5.fromNumber(-1.7e-38), equalTo(Mflpt5(0x03, 0xb9, 0x1d, 0x15, 0x63))) + assertThat(Mflpt5.fromNumber(-1.7e-39), equalTo(Mflpt5(0x00, 0x00, 0x00, 0x00, 0x00))) + assertFailsWith { Mflpt5.fromNumber(1.7014118346e+38) } + assertFailsWith { Mflpt5.fromNumber(-1.7014118346e+38) } + assertFailsWith { Mflpt5.fromNumber(1.7014118347e+38) } + assertFailsWith { Mflpt5.fromNumber(-1.7014118347e+38) } + } + + @Test + fun testMflpt5ToFloat() { + val epsilon=0.000000001 + assertThat(Mflpt5(0x00, 0x00, 0x00, 0x00, 0x00).toDouble(), equalTo(0.0)) + assertThat(Mflpt5(0x82, 0x49, 0x0F, 0xDA, 0xA1).toDouble(), closeTo(3.141592653, epsilon)) + assertThat(Mflpt5(0x82, 0x49, 0x0F, 0xDA, 0xA2).toDouble(), closeTo(3.141592653589793, epsilon)) + assertThat(Mflpt5(0x90, 0x00, 0x00, 0x00, 0x00).toDouble(), equalTo(32768.0)) + assertThat(Mflpt5(0x90, 0x80, 0x00, 0x00, 0x00).toDouble(), equalTo(-32768.0)) + assertThat(Mflpt5(0x81, 0x00, 0x00, 0x00, 0x00).toDouble(), equalTo(1.0)) + assertThat(Mflpt5(0x80, 0x35, 0x04, 0xF3, 0x34).toDouble(), closeTo(0.7071067812, epsilon)) + assertThat(Mflpt5(0x80, 0x35, 0x04, 0xF3, 0x33).toDouble(), closeTo(0.7071067811865476, epsilon)) + assertThat(Mflpt5(0x81, 0x35, 0x04, 0xF3, 0x34).toDouble(), closeTo(1.4142135624, epsilon)) + assertThat(Mflpt5(0x81, 0x35, 0x04, 0xF3, 0x33).toDouble(), closeTo(1.4142135623730951, epsilon)) + assertThat(Mflpt5(0x80, 0x80, 0x00, 0x00, 0x00).toDouble(), equalTo(-.5)) + assertThat(Mflpt5(0x80, 0x31, 0x72, 0x17, 0xF8).toDouble(), closeTo(0.69314718061, epsilon)) + assertThat(Mflpt5(0x80, 0x31, 0x72, 0x17, 0xF7).toDouble(), closeTo(0.6931471805599453, epsilon)) + assertThat(Mflpt5(0x84, 0x20, 0x00, 0x00, 0x00).toDouble(), equalTo(10.0)) + assertThat(Mflpt5(0x9E, 0x6E, 0x6B, 0x28, 0x00).toDouble(), equalTo(1000000000.0)) + assertThat(Mflpt5(0x80, 0x00, 0x00, 0x00, 0x00).toDouble(), equalTo(.5)) + assertThat(Mflpt5(0x81, 0x38, 0xAA, 0x3B, 0x29).toDouble(), closeTo(1.4426950408889634, epsilon)) + assertThat(Mflpt5(0x81, 0x49, 0x0F, 0xDA, 0xA2).toDouble(), closeTo(1.5707963267948966, epsilon)) + assertThat(Mflpt5(0x83, 0x49, 0x0F, 0xDA, 0xA2).toDouble(), closeTo(6.283185307179586, epsilon)) + assertThat(Mflpt5(0x7F, 0x00, 0x00, 0x00, 0x00).toDouble(), equalTo(.25)) + assertThat(Mflpt5(0xd1, 0x02, 0xb7, 0x06, 0xfb).toDouble(), closeTo(123.45678e22, 1.0e15)) + assertThat(Mflpt5(0x3e, 0xe9, 0x34, 0x09, 0x1b).toDouble(), closeTo(-123.45678e-22, epsilon)) + } +} diff --git a/compiler/test/LiteralValueTests.kt b/compiler/test/TestParserNumericLiteralValue.kt similarity index 98% rename from compiler/test/LiteralValueTests.kt rename to compiler/test/TestParserNumericLiteralValue.kt index b7192f6cd..040cb3ebf 100644 --- a/compiler/test/LiteralValueTests.kt +++ b/compiler/test/TestParserNumericLiteralValue.kt @@ -14,14 +14,14 @@ import kotlin.test.assertNotEquals import kotlin.test.assertTrue -private fun sameValueAndType(lv1: NumericLiteralValue, lv2: NumericLiteralValue): Boolean { - return lv1.type==lv2.type && lv1==lv2 -} - @TestInstance(TestInstance.Lifecycle.PER_CLASS) class TestParserNumericLiteralValue { + private fun sameValueAndType(lv1: NumericLiteralValue, lv2: NumericLiteralValue): Boolean { + return lv1.type==lv2.type && lv1==lv2 + } + private val dummyPos = Position("test", 0, 0, 0) @Test diff --git a/compiler/test/TestPetscii.kt b/compiler/test/TestPetscii.kt new file mode 100644 index 000000000..c83657810 --- /dev/null +++ b/compiler/test/TestPetscii.kt @@ -0,0 +1,108 @@ +package prog8tests + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import prog8.ast.base.DataType +import prog8.ast.base.Position +import prog8.ast.expressions.NumericLiteralValue +import prog8.ast.expressions.StringLiteralValue +import prog8.compiler.target.cbm.Petscii +import kotlin.test.* + + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class TestPetscii { + + @Test + fun testZero() { + assertThat(Petscii.encodePetscii("\u0000", true), equalTo(listOf(0))) + assertThat(Petscii.encodePetscii("\u0000", false), equalTo(listOf(0))) + assertThat(Petscii.decodePetscii(listOf(0), true), equalTo("\u0000")) + assertThat(Petscii.decodePetscii(listOf(0), false), equalTo("\u0000")) + } + + @Test + fun testLowercase() { + assertThat(Petscii.encodePetscii("hello WORLD 123 @!£", true), equalTo( + listOf(72, 69, 76, 76, 79, 32, 0xd7, 0xcf, 0xd2, 0xcc, 0xc4, 32, 49, 50, 51, 32, 64, 33, 0x5c))) + assertThat(Petscii.encodePetscii("\uf11a", true), equalTo(listOf(0x12))) // reverse vid + assertThat(Petscii.encodePetscii("✓", true), equalTo(listOf(0xfa))) + assertThat("expect lowercase error fallback", Petscii.encodePetscii("π", true), equalTo(listOf(255))) + assertThat("expect lowercase error fallback", Petscii.encodePetscii("♥", true), equalTo(listOf(0xd3))) + + assertThat(Petscii.decodePetscii(listOf(72, 0xd7, 0x5c, 0xfa, 0x12), true), equalTo("hW£✓\uF11A")) + assertFailsWith { Petscii.decodePetscii(listOf(-1), true) } + assertFailsWith { Petscii.decodePetscii(listOf(256), true) } + } + + @Test + fun testUppercase() { + assertThat(Petscii.encodePetscii("HELLO 123 @!£"), equalTo( + listOf(72, 69, 76, 76, 79, 32, 49, 50, 51, 32, 64, 33, 0x5c))) + assertThat(Petscii.encodePetscii("\uf11a"), equalTo(listOf(0x12))) // reverse vid + assertThat(Petscii.encodePetscii("♥"), equalTo(listOf(0xd3))) + assertThat(Petscii.encodePetscii("π"), equalTo(listOf(0xff))) + assertThat("expecting fallback", Petscii.encodePetscii("✓"), equalTo(listOf(250))) + + assertThat(Petscii.decodePetscii(listOf(72, 0x5c, 0xd3, 0xff)), equalTo("H£♥π")) + assertFailsWith { Petscii.decodePetscii(listOf(-1)) } + assertFailsWith { Petscii.decodePetscii(listOf(256)) } + } + + @Test + fun testScreencodeLowercase() { + assertThat(Petscii.encodeScreencode("hello WORLD 123 @!£", true), equalTo( + listOf(0x08, 0x05, 0x0c, 0x0c, 0x0f, 0x20, 0x57, 0x4f, 0x52, 0x4c, 0x44, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c) + )) + assertThat(Petscii.encodeScreencode("✓", true), equalTo(listOf(0x7a))) + assertThat("expect fallback", Petscii.encodeScreencode("♥", true), equalTo(listOf(83))) + assertThat("expect fallback", Petscii.encodeScreencode("π", true), equalTo(listOf(94))) + + assertThat(Petscii.decodeScreencode(listOf(0x08, 0x57, 0x1c, 0x7a), true), equalTo("hW£✓")) + assertFailsWith { Petscii.decodeScreencode(listOf(-1), true) } + assertFailsWith { Petscii.decodeScreencode(listOf(256), true) } + } + + @Test + fun testScreencodeUppercase() { + assertThat(Petscii.encodeScreencode("WORLD 123 @!£"), equalTo( + listOf(0x17, 0x0f, 0x12, 0x0c, 0x04, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c))) + assertThat(Petscii.encodeScreencode("♥"), equalTo(listOf(0x53))) + assertThat(Petscii.encodeScreencode("π"), equalTo(listOf(0x5e))) + assertThat(Petscii.encodeScreencode("HELLO"), equalTo(listOf(8, 5, 12, 12, 15))) + assertThat("expecting fallback", Petscii.encodeScreencode("hello"), equalTo(listOf(8, 5, 12, 12, 15))) + assertThat("expecting fallback", Petscii.encodeScreencode("✓"), equalTo(listOf(122))) + + assertThat(Petscii.decodeScreencode(listOf(0x17, 0x1c, 0x53, 0x5e)), equalTo("W£♥π")) + assertFailsWith { Petscii.decodeScreencode(listOf(-1)) } + assertFailsWith { Petscii.decodeScreencode(listOf(256)) } + } + + @Test + fun testLiteralValueComparisons() { + val ten = NumericLiteralValue(DataType.UWORD, 10, Position.DUMMY) + val nine = NumericLiteralValue(DataType.UBYTE, 9, Position.DUMMY) + assertEquals(ten, ten) + assertNotEquals(ten, nine) + assertFalse(ten != ten) + assertTrue(ten != nine) + + assertTrue(ten > nine) + assertTrue(ten >= nine) + assertTrue(ten >= ten) + assertFalse(ten > ten) + + assertFalse(ten < nine) + assertFalse(ten <= nine) + assertTrue(ten <= ten) + assertFalse(ten < ten) + + val abc = StringLiteralValue("abc", false, Position.DUMMY) + val abd = StringLiteralValue("abd", false, Position.DUMMY) + assertEquals(abc, abc) + assertTrue(abc!=abd) + assertFalse(abc!=abc) + } +} diff --git a/compiler/test/UnitTests.kt b/compiler/test/UnitTests.kt deleted file mode 100644 index e6e7654f9..000000000 --- a/compiler/test/UnitTests.kt +++ /dev/null @@ -1,649 +0,0 @@ -package prog8tests - -import org.hamcrest.MatcherAssert.assertThat -import org.hamcrest.Matchers.closeTo -import org.hamcrest.Matchers.equalTo -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.TestInstance -import prog8.ast.* -import prog8.ast.base.DataType -import prog8.ast.base.ParentSentinel -import prog8.ast.base.Position -import prog8.ast.base.VarDeclType -import prog8.ast.expressions.* -import prog8.ast.statements.* -import prog8.compiler.* -import prog8.compiler.target.C64Target -import prog8.compiler.target.Cx16Target -import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage -import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_NEGATIVE -import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_POSITIVE -import prog8.compiler.target.c64.C64MachineDefinition.Mflpt5 -import prog8.compiler.target.cbm.Petscii -import prog8.compiler.target.cx16.CX16MachineDefinition.CX16Zeropage -import java.nio.file.Path -import kotlin.test.* - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -class TestCompiler { - @Test - fun testToHex() { - assertEquals("0", 0.toHex()) - assertEquals("1", 1.toHex()) - assertEquals("1", 1.234.toHex()) - assertEquals("10", 10.toHex()) - assertEquals("10", 10.99.toHex()) - assertEquals("15", 15.toHex()) - assertEquals("\$10", 16.toHex()) - assertEquals("\$ff", 255.toHex()) - assertEquals("\$0100", 256.toHex()) - assertEquals("\$4e5c", 20060.toHex()) - assertEquals("\$c382", 50050.toHex()) - assertEquals("\$ffff", 65535.toHex()) - assertEquals("\$ffff", 65535L.toHex()) - assertEquals("0", 0.toHex()) - assertEquals("-1", (-1).toHex()) - assertEquals("-1", (-1.234).toHex()) - assertEquals("-10", (-10).toHex()) - assertEquals("-10", (-10.99).toHex()) - assertEquals("-15", (-15).toHex()) - assertEquals("-\$10", (-16).toHex()) - assertEquals("-\$ff", (-255).toHex()) - assertEquals("-\$0100", (-256).toHex()) - assertEquals("-\$4e5c", (-20060).toHex()) - assertEquals("-\$c382", (-50050).toHex()) - assertEquals("-\$ffff", (-65535).toHex()) - assertEquals("-\$ffff", (-65535L).toHex()) - assertFailsWith { 65536.toHex() } - assertFailsWith { 65536L.toHex() } - } - - @Test - fun testFloatToMflpt5() { - assertThat(Mflpt5.fromNumber(0), equalTo(Mflpt5(0x00, 0x00, 0x00, 0x00, 0x00))) - assertThat(Mflpt5.fromNumber(3.141592653), equalTo(Mflpt5(0x82, 0x49, 0x0F, 0xDA, 0xA1))) - assertThat(Mflpt5.fromNumber(3.141592653589793), equalTo(Mflpt5(0x82, 0x49, 0x0F, 0xDA, 0xA2))) - assertThat(Mflpt5.fromNumber(32768), equalTo(Mflpt5(0x90, 0x00, 0x00, 0x00, 0x00))) - assertThat(Mflpt5.fromNumber(-32768), equalTo(Mflpt5(0x90, 0x80, 0x00, 0x00, 0x00))) - assertThat(Mflpt5.fromNumber(1), equalTo(Mflpt5(0x81, 0x00, 0x00, 0x00, 0x00))) - assertThat(Mflpt5.fromNumber(0.7071067812), equalTo(Mflpt5(0x80, 0x35, 0x04, 0xF3, 0x34))) - assertThat(Mflpt5.fromNumber(0.7071067811865476), equalTo(Mflpt5(0x80, 0x35, 0x04, 0xF3, 0x33))) - assertThat(Mflpt5.fromNumber(1.4142135624), equalTo(Mflpt5(0x81, 0x35, 0x04, 0xF3, 0x34))) - assertThat(Mflpt5.fromNumber(1.4142135623730951), equalTo(Mflpt5(0x81, 0x35, 0x04, 0xF3, 0x33))) - assertThat(Mflpt5.fromNumber(-.5), equalTo(Mflpt5(0x80, 0x80, 0x00, 0x00, 0x00))) - assertThat(Mflpt5.fromNumber(0.69314718061), equalTo(Mflpt5(0x80, 0x31, 0x72, 0x17, 0xF8))) - assertThat(Mflpt5.fromNumber(0.6931471805599453), equalTo(Mflpt5(0x80, 0x31, 0x72, 0x17, 0xF7))) - assertThat(Mflpt5.fromNumber(10), equalTo(Mflpt5(0x84, 0x20, 0x00, 0x00, 0x00))) - assertThat(Mflpt5.fromNumber(1000000000), equalTo(Mflpt5(0x9E, 0x6E, 0x6B, 0x28, 0x00))) - assertThat(Mflpt5.fromNumber(.5), equalTo(Mflpt5(0x80, 0x00, 0x00, 0x00, 0x00))) - assertThat(Mflpt5.fromNumber(1.4426950408889634), equalTo(Mflpt5(0x81, 0x38, 0xAA, 0x3B, 0x29))) - assertThat(Mflpt5.fromNumber(1.5707963267948966), equalTo(Mflpt5(0x81, 0x49, 0x0F, 0xDA, 0xA2))) - assertThat(Mflpt5.fromNumber(6.283185307179586), equalTo(Mflpt5(0x83, 0x49, 0x0F, 0xDA, 0xA2))) - assertThat(Mflpt5.fromNumber(.25), equalTo(Mflpt5(0x7F, 0x00, 0x00, 0x00, 0x00))) - assertThat(Mflpt5.fromNumber(123.45678e22), equalTo(Mflpt5(0xd1, 0x02, 0xb7, 0x06, 0xfb))) - assertThat(Mflpt5.fromNumber(-123.45678e-22), equalTo(Mflpt5(0x3e, 0xe9, 0x34, 0x09, 0x1b))) - } - - @Test - fun testFloatRange() { - assertThat(Mflpt5.fromNumber(FLOAT_MAX_POSITIVE), equalTo(Mflpt5(0xff, 0x7f, 0xff, 0xff, 0xff))) - assertThat(Mflpt5.fromNumber(FLOAT_MAX_NEGATIVE), equalTo(Mflpt5(0xff, 0xff, 0xff, 0xff, 0xff))) - assertThat(Mflpt5.fromNumber(1.7e-38), equalTo(Mflpt5(0x03, 0x39, 0x1d, 0x15, 0x63))) - assertThat(Mflpt5.fromNumber(1.7e-39), equalTo(Mflpt5(0x00, 0x00, 0x00, 0x00, 0x00))) - assertThat(Mflpt5.fromNumber(-1.7e-38), equalTo(Mflpt5(0x03, 0xb9, 0x1d, 0x15, 0x63))) - assertThat(Mflpt5.fromNumber(-1.7e-39), equalTo(Mflpt5(0x00, 0x00, 0x00, 0x00, 0x00))) - assertFailsWith { Mflpt5.fromNumber(1.7014118346e+38) } - assertFailsWith { Mflpt5.fromNumber(-1.7014118346e+38) } - assertFailsWith { Mflpt5.fromNumber(1.7014118347e+38) } - assertFailsWith { Mflpt5.fromNumber(-1.7014118347e+38) } - } - - @Test - fun testMflpt5ToFloat() { - val epsilon=0.000000001 - assertThat(Mflpt5(0x00, 0x00, 0x00, 0x00, 0x00).toDouble(), equalTo(0.0)) - assertThat(Mflpt5(0x82, 0x49, 0x0F, 0xDA, 0xA1).toDouble(), closeTo(3.141592653, epsilon)) - assertThat(Mflpt5(0x82, 0x49, 0x0F, 0xDA, 0xA2).toDouble(), closeTo(3.141592653589793, epsilon)) - assertThat(Mflpt5(0x90, 0x00, 0x00, 0x00, 0x00).toDouble(), equalTo(32768.0)) - assertThat(Mflpt5(0x90, 0x80, 0x00, 0x00, 0x00).toDouble(), equalTo(-32768.0)) - assertThat(Mflpt5(0x81, 0x00, 0x00, 0x00, 0x00).toDouble(), equalTo(1.0)) - assertThat(Mflpt5(0x80, 0x35, 0x04, 0xF3, 0x34).toDouble(), closeTo(0.7071067812, epsilon)) - assertThat(Mflpt5(0x80, 0x35, 0x04, 0xF3, 0x33).toDouble(), closeTo(0.7071067811865476, epsilon)) - assertThat(Mflpt5(0x81, 0x35, 0x04, 0xF3, 0x34).toDouble(), closeTo(1.4142135624, epsilon)) - assertThat(Mflpt5(0x81, 0x35, 0x04, 0xF3, 0x33).toDouble(), closeTo(1.4142135623730951, epsilon)) - assertThat(Mflpt5(0x80, 0x80, 0x00, 0x00, 0x00).toDouble(), equalTo(-.5)) - assertThat(Mflpt5(0x80, 0x31, 0x72, 0x17, 0xF8).toDouble(), closeTo(0.69314718061, epsilon)) - assertThat(Mflpt5(0x80, 0x31, 0x72, 0x17, 0xF7).toDouble(), closeTo(0.6931471805599453, epsilon)) - assertThat(Mflpt5(0x84, 0x20, 0x00, 0x00, 0x00).toDouble(), equalTo(10.0)) - assertThat(Mflpt5(0x9E, 0x6E, 0x6B, 0x28, 0x00).toDouble(), equalTo(1000000000.0)) - assertThat(Mflpt5(0x80, 0x00, 0x00, 0x00, 0x00).toDouble(), equalTo(.5)) - assertThat(Mflpt5(0x81, 0x38, 0xAA, 0x3B, 0x29).toDouble(), closeTo(1.4426950408889634, epsilon)) - assertThat(Mflpt5(0x81, 0x49, 0x0F, 0xDA, 0xA2).toDouble(), closeTo(1.5707963267948966, epsilon)) - assertThat(Mflpt5(0x83, 0x49, 0x0F, 0xDA, 0xA2).toDouble(), closeTo(6.283185307179586, epsilon)) - assertThat(Mflpt5(0x7F, 0x00, 0x00, 0x00, 0x00).toDouble(), equalTo(.25)) - assertThat(Mflpt5(0xd1, 0x02, 0xb7, 0x06, 0xfb).toDouble(), closeTo(123.45678e22, 1.0e15)) - assertThat(Mflpt5(0x3e, 0xe9, 0x34, 0x09, 0x1b).toDouble(), closeTo(-123.45678e-22, epsilon)) - } -} - - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -class TestC64Zeropage { - - private val errors = ErrorReporter() - - @Test - fun testNames() { - val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, C64Target)) - - zp.allocate("", DataType.UBYTE, null, errors) - zp.allocate("", DataType.UBYTE, null, errors) - zp.allocate("varname", DataType.UBYTE, null, errors) - assertFailsWith { - zp.allocate("varname", DataType.UBYTE, null, errors) - } - zp.allocate("varname2", DataType.UBYTE, null, errors) - } - - @Test - fun testZpFloatEnable() { - val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) - assertFailsWith { - zp.allocate("", DataType.FLOAT, null, errors) - } - val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, false, C64Target)) - assertFailsWith { - zp2.allocate("", DataType.FLOAT, null, errors) - } - val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false, C64Target)) - zp3.allocate("", DataType.FLOAT, null, errors) - } - - @Test - fun testZpModesWithFloats() { - C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) - C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, C64Target)) - C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, C64Target)) - C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false, C64Target)) - C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target)) - C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false, C64Target)) - assertFailsWith { - C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), true, false, C64Target)) - } - assertFailsWith { - C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true, false, C64Target)) - } - } - - @Test - fun testZpDontuse() { - val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, false, C64Target)) - println(zp.free) - assertEquals(0, zp.availableBytes()) - assertFailsWith { - zp.allocate("", DataType.BYTE, null, errors) - } - } - - @Test - fun testFreeSpacesBytes() { - val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target)) - assertEquals(18, zp1.availableBytes()) - val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false, C64Target)) - assertEquals(85, zp2.availableBytes()) - val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, C64Target)) - assertEquals(125, zp3.availableBytes()) - val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) - assertEquals(238, zp4.availableBytes()) - zp4.allocate("test", DataType.UBYTE, null, errors) - assertEquals(237, zp4.availableBytes()) - zp4.allocate("test2", DataType.UBYTE, null, errors) - assertEquals(236, zp4.availableBytes()) - } - - @Test - fun testFreeSpacesWords() { - val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target)) - assertEquals(6, zp1.availableWords()) - val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false, C64Target)) - assertEquals(38, zp2.availableWords()) - val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, C64Target)) - assertEquals(57, zp3.availableWords()) - val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) - assertEquals(116, zp4.availableWords()) - zp4.allocate("test", DataType.UWORD, null, errors) - assertEquals(115, zp4.availableWords()) - zp4.allocate("test2", DataType.UWORD, null, errors) - assertEquals(114, zp4.availableWords()) - } - - @Test - fun testReservedSpace() { - val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) - assertEquals(238, zp1.availableBytes()) - assertTrue(50 in zp1.free) - assertTrue(100 in zp1.free) - assertTrue(49 in zp1.free) - assertTrue(101 in zp1.free) - assertTrue(200 in zp1.free) - assertTrue(255 in zp1.free) - assertTrue(199 in zp1.free) - val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, listOf(50 .. 100, 200..255), false, false, C64Target)) - assertEquals(139, zp2.availableBytes()) - assertFalse(50 in zp2.free) - assertFalse(100 in zp2.free) - assertTrue(49 in zp2.free) - assertTrue(101 in zp2.free) - assertFalse(200 in zp2.free) - assertFalse(255 in zp2.free) - assertTrue(199 in zp2.free) - } - - @Test - fun testBasicsafeAllocation() { - val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target)) - assertEquals(18, zp.availableBytes()) - assertTrue(zp.hasByteAvailable()) - assertTrue(zp.hasWordAvailable()) - - assertFailsWith { - // in regular zp there aren't 5 sequential bytes free - zp.allocate("", DataType.FLOAT, null, errors) - } - - for (i in 0 until zp.availableBytes()) { - val loc = zp.allocate("", DataType.UBYTE, null, errors) - assertTrue(loc > 0) - } - assertEquals(0, zp.availableBytes()) - assertFalse(zp.hasByteAvailable()) - assertFalse(zp.hasWordAvailable()) - assertFailsWith { - zp.allocate("", DataType.UBYTE, null, errors) - } - assertFailsWith { - zp.allocate("", DataType.UWORD, null, errors) - } - } - - @Test - fun testFullAllocation() { - val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) - assertEquals(238, zp.availableBytes()) - assertTrue(zp.hasByteAvailable()) - assertTrue(zp.hasWordAvailable()) - val loc = zp.allocate("", DataType.UWORD, null, errors) - assertTrue(loc > 3) - assertFalse(loc in zp.free) - val num = zp.availableBytes() / 2 - - for(i in 0..num-4) { - zp.allocate("", DataType.UWORD, null, errors) - } - assertEquals(6,zp.availableBytes()) - - assertFailsWith { - // can't allocate because no more sequential bytes, only fragmented - zp.allocate("", DataType.UWORD, null, errors) - } - - for(i in 0..5) { - zp.allocate("", DataType.UBYTE, null, errors) - } - - assertEquals(0, zp.availableBytes()) - assertFalse(zp.hasByteAvailable()) - assertFalse(zp.hasWordAvailable()) - assertFailsWith { - // no more space - zp.allocate("", DataType.UBYTE, null, errors) - } - } - - @Test - fun testEfficientAllocation() { - val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target)) - assertEquals(18, zp.availableBytes()) - assertEquals(0x04, zp.allocate("", DataType.WORD, null, errors)) - assertEquals(0x06, zp.allocate("", DataType.UBYTE, null, errors)) - assertEquals(0x0a, zp.allocate("", DataType.UBYTE, null, errors)) - assertEquals(0x9b, zp.allocate("", DataType.UWORD, null, errors)) - assertEquals(0x9e, zp.allocate("", DataType.UWORD, null, errors)) - assertEquals(0xa5, zp.allocate("", DataType.UWORD, null, errors)) - assertEquals(0xb0, zp.allocate("", DataType.UWORD, null, errors)) - assertEquals(0xbe, zp.allocate("", DataType.UWORD, null, errors)) - assertEquals(0x0e, zp.allocate("", DataType.UBYTE, null, errors)) - assertEquals(0x92, zp.allocate("", DataType.UBYTE, null, errors)) - assertEquals(0x96, zp.allocate("", DataType.UBYTE, null, errors)) - assertEquals(0xf9, zp.allocate("", DataType.UBYTE, null, errors)) - assertEquals(0, zp.availableBytes()) - } - - @Test - fun testReservedLocations() { - val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, C64Target)) - assertEquals(zp.SCRATCH_REG, zp.SCRATCH_B1+1, "zp _B1 and _REG must be next to each other to create a word") - } -} - - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -class TestCx16Zeropage { - private val errors = ErrorReporter() - - @Test - fun testReservedLocations() { - val zp = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, Cx16Target)) - assertEquals(zp.SCRATCH_REG, zp.SCRATCH_B1+1, "zp _B1 and _REG must be next to each other to create a word") - } - - @Test - fun testFreeSpacesBytes() { - val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, Cx16Target)) - assertEquals(88, zp1.availableBytes()) - val zp2 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, Cx16Target)) - assertEquals(175, zp2.availableBytes()) - val zp3 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, Cx16Target)) - assertEquals(216, zp3.availableBytes()) - zp3.allocate("test", DataType.UBYTE, null, errors) - assertEquals(215, zp3.availableBytes()) - zp3.allocate("test2", DataType.UBYTE, null, errors) - assertEquals(214, zp3.availableBytes()) - } - - @Test - fun testFreeSpacesWords() { - val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, Cx16Target)) - assertEquals(108, zp1.availableWords()) - val zp2 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, Cx16Target)) - assertEquals(87, zp2.availableWords()) - val zp3 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, Cx16Target)) - assertEquals(44, zp3.availableWords()) - zp3.allocate("test", DataType.UWORD, null, errors) - assertEquals(43, zp3.availableWords()) - zp3.allocate("test2", DataType.UWORD, null, errors) - assertEquals(42, zp3.availableWords()) - } - - @Test - fun testReservedSpace() { - val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, Cx16Target)) - assertEquals(216, zp1.availableBytes()) - assertTrue(0x22 in zp1.free) - assertTrue(0x80 in zp1.free) - assertTrue(0xff in zp1.free) - assertFalse(0x02 in zp1.free) - assertFalse(0x21 in zp1.free) - } -} - - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -class TestPetscii { - - @Test - fun testZero() { - assertThat(Petscii.encodePetscii("\u0000", true), equalTo(listOf(0))) - assertThat(Petscii.encodePetscii("\u0000", false), equalTo(listOf(0))) - assertThat(Petscii.decodePetscii(listOf(0), true), equalTo("\u0000")) - assertThat(Petscii.decodePetscii(listOf(0), false), equalTo("\u0000")) - } - - @Test - fun testLowercase() { - assertThat(Petscii.encodePetscii("hello WORLD 123 @!£", true), equalTo( - listOf(72, 69, 76, 76, 79, 32, 0xd7, 0xcf, 0xd2, 0xcc, 0xc4, 32, 49, 50, 51, 32, 64, 33, 0x5c))) - assertThat(Petscii.encodePetscii("\uf11a", true), equalTo(listOf(0x12))) // reverse vid - assertThat(Petscii.encodePetscii("✓", true), equalTo(listOf(0xfa))) - assertThat("expect lowercase error fallback", Petscii.encodePetscii("π", true), equalTo(listOf(255))) - assertThat("expect lowercase error fallback", Petscii.encodePetscii("♥", true), equalTo(listOf(0xd3))) - - assertThat(Petscii.decodePetscii(listOf(72, 0xd7, 0x5c, 0xfa, 0x12), true), equalTo("hW£✓\uF11A")) - assertFailsWith { Petscii.decodePetscii(listOf(-1), true) } - assertFailsWith { Petscii.decodePetscii(listOf(256), true) } - } - - @Test - fun testUppercase() { - assertThat(Petscii.encodePetscii("HELLO 123 @!£"), equalTo( - listOf(72, 69, 76, 76, 79, 32, 49, 50, 51, 32, 64, 33, 0x5c))) - assertThat(Petscii.encodePetscii("\uf11a"), equalTo(listOf(0x12))) // reverse vid - assertThat(Petscii.encodePetscii("♥"), equalTo(listOf(0xd3))) - assertThat(Petscii.encodePetscii("π"), equalTo(listOf(0xff))) - assertThat("expecting fallback", Petscii.encodePetscii("✓"), equalTo(listOf(250))) - - assertThat(Petscii.decodePetscii(listOf(72, 0x5c, 0xd3, 0xff)), equalTo("H£♥π")) - assertFailsWith { Petscii.decodePetscii(listOf(-1)) } - assertFailsWith { Petscii.decodePetscii(listOf(256)) } - } - - @Test - fun testScreencodeLowercase() { - assertThat(Petscii.encodeScreencode("hello WORLD 123 @!£", true), equalTo( - listOf(0x08, 0x05, 0x0c, 0x0c, 0x0f, 0x20, 0x57, 0x4f, 0x52, 0x4c, 0x44, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c) - )) - assertThat(Petscii.encodeScreencode("✓", true), equalTo(listOf(0x7a))) - assertThat("expect fallback", Petscii.encodeScreencode("♥", true), equalTo(listOf(83))) - assertThat("expect fallback", Petscii.encodeScreencode("π", true), equalTo(listOf(94))) - - assertThat(Petscii.decodeScreencode(listOf(0x08, 0x57, 0x1c, 0x7a), true), equalTo("hW£✓")) - assertFailsWith { Petscii.decodeScreencode(listOf(-1), true) } - assertFailsWith { Petscii.decodeScreencode(listOf(256), true) } - } - - @Test - fun testScreencodeUppercase() { - assertThat(Petscii.encodeScreencode("WORLD 123 @!£"), equalTo( - listOf(0x17, 0x0f, 0x12, 0x0c, 0x04, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c))) - assertThat(Petscii.encodeScreencode("♥"), equalTo(listOf(0x53))) - assertThat(Petscii.encodeScreencode("π"), equalTo(listOf(0x5e))) - assertThat(Petscii.encodeScreencode("HELLO"), equalTo(listOf(8, 5, 12, 12, 15))) - assertThat("expecting fallback", Petscii.encodeScreencode("hello"), equalTo(listOf(8, 5, 12, 12, 15))) - assertThat("expecting fallback", Petscii.encodeScreencode("✓"), equalTo(listOf(122))) - - assertThat(Petscii.decodeScreencode(listOf(0x17, 0x1c, 0x53, 0x5e)), equalTo("W£♥π")) - assertFailsWith { Petscii.decodeScreencode(listOf(-1)) } - assertFailsWith { Petscii.decodeScreencode(listOf(256)) } - } - - @Test - fun testLiteralValueComparisons() { - val ten = NumericLiteralValue(DataType.UWORD, 10, Position.DUMMY) - val nine = NumericLiteralValue(DataType.UBYTE, 9, Position.DUMMY) - assertEquals(ten, ten) - assertNotEquals(ten, nine) - assertFalse(ten != ten) - assertTrue(ten != nine) - - assertTrue(ten > nine) - assertTrue(ten >= nine) - assertTrue(ten >= ten) - assertFalse(ten > ten) - - assertFalse(ten < nine) - assertFalse(ten <= nine) - assertTrue(ten <= ten) - assertFalse(ten < ten) - - val abc = StringLiteralValue("abc", false, Position.DUMMY) - val abd = StringLiteralValue("abd", false, Position.DUMMY) - assertEquals(abc, abc) - assertTrue(abc!=abd) - assertFalse(abc!=abc) - } -} - - -class TestMemory { - private class DummyFunctions: IBuiltinFunctions { - override val names: Set = emptySet() - override val purefunctionNames: Set = emptySet() - override fun constValue(name: String, args: List, position: Position, memsizer: IMemSizer): NumericLiteralValue? = null - override fun returnType(name: String, args: MutableList) = InferredTypes.InferredType.unknown() - } - - private class DummyMemsizer: IMemSizer { - override fun memorySize(dt: DataType): Int = 0 - } - - @Test - fun testInValidRamC64_memory_addresses() { - - var memexpr = NumericLiteralValue.optimalInteger(0x0000, Position.DUMMY) - var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - val program = Program("test", mutableListOf(), DummyFunctions(), DummyMemsizer()) - assertTrue(C64Target.isInRegularRAM(target, program)) - - memexpr = NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY) - target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - assertTrue(C64Target.isInRegularRAM(target, program)) - - memexpr = NumericLiteralValue.optimalInteger(0x9fff, Position.DUMMY) - target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - assertTrue(C64Target.isInRegularRAM(target, program)) - - memexpr = NumericLiteralValue.optimalInteger(0xc000, Position.DUMMY) - target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - assertTrue(C64Target.isInRegularRAM(target, program)) - - memexpr = NumericLiteralValue.optimalInteger(0xcfff, Position.DUMMY) - target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - assertTrue(C64Target.isInRegularRAM(target, program)) - } - - @Test - fun testNotInValidRamC64_memory_addresses() { - - var memexpr = NumericLiteralValue.optimalInteger(0xa000, Position.DUMMY) - var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - val program = Program("test", mutableListOf(), DummyFunctions(), DummyMemsizer()) - assertFalse(C64Target.isInRegularRAM(target, program)) - - memexpr = NumericLiteralValue.optimalInteger(0xafff, Position.DUMMY) - target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - assertFalse(C64Target.isInRegularRAM(target, program)) - - memexpr = NumericLiteralValue.optimalInteger(0xd000, Position.DUMMY) - target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - assertFalse(C64Target.isInRegularRAM(target, program)) - - memexpr = NumericLiteralValue.optimalInteger(0xffff, Position.DUMMY) - target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - assertFalse(C64Target.isInRegularRAM(target, program)) - } - - @Test - fun testInValidRamC64_memory_identifiers() { - var target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.VAR) - val program = Program("test", mutableListOf(), DummyFunctions(), DummyMemsizer()) - - assertTrue(C64Target.isInRegularRAM(target, program)) - target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.VAR) - assertFalse(C64Target.isInRegularRAM(target, program)) - target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.CONST) - assertTrue(C64Target.isInRegularRAM(target, program)) - target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.CONST) - assertFalse(C64Target.isInRegularRAM(target, program)) - target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.MEMORY) - assertFalse(C64Target.isInRegularRAM(target, program)) - } - - @Test - private fun createTestProgramForMemoryRefViaVar(address: Int, vartype: VarDeclType): AssignTarget { - val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) - val memexpr = IdentifierReference(listOf("address"), Position.DUMMY) - val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) - val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) - val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) - module.linkParents(ParentSentinel) - return target - } - - @Test - fun testInValidRamC64_memory_expression() { - val memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY), Position.DUMMY) - val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY) - val program = Program("test", mutableListOf(), DummyFunctions(), DummyMemsizer()) - assertFalse(C64Target.isInRegularRAM(target, program)) - } - - @Test - fun testInValidRamC64_variable() { - val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY) - val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) - val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) - val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) - val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) - val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) - module.linkParents(ParentSentinel) - assertTrue(C64Target.isInRegularRAM(target, program)) - } - - @Test - fun testInValidRamC64_memmap_variable() { - val address = 0x1000 - val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) - val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) - val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) - val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) - val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) - val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) - module.linkParents(ParentSentinel) - assertTrue(C64Target.isInRegularRAM(target, program)) - } - - @Test - fun testNotInValidRamC64_memmap_variable() { - val address = 0xd020 - val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) - val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY) - val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) - val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) - val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) - val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) - module.linkParents(ParentSentinel) - assertFalse(C64Target.isInRegularRAM(target, program)) - } - - @Test - fun testInValidRamC64_array() { - val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, false, false, false, Position.DUMMY) - val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) - val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) - val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) - val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) - val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) - val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) - module.linkParents(ParentSentinel) - assertTrue(C64Target.isInRegularRAM(target, program)) - } - - @Test - fun testInValidRamC64_array_memmapped() { - val address = 0x1000 - val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) - val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) - val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) - val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) - val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) - val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) - val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) - module.linkParents(ParentSentinel) - assertTrue(C64Target.isInRegularRAM(target, program)) - } - - @Test - fun testNotValidRamC64_array_memmapped() { - val address = 0xe000 - val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) - val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) - val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) - val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) - val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) - val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of("")) - val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer()) - module.linkParents(ParentSentinel) - assertFalse(C64Target.isInRegularRAM(target, program)) - } -} diff --git a/compiler/test/ZeropageTests.kt b/compiler/test/ZeropageTests.kt new file mode 100644 index 000000000..8e2a3a6b7 --- /dev/null +++ b/compiler/test/ZeropageTests.kt @@ -0,0 +1,265 @@ +package prog8tests + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import prog8.ast.base.DataType +import prog8.compiler.* +import prog8.compiler.target.C64Target +import prog8.compiler.target.Cx16Target +import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage +import prog8.compiler.target.cx16.CX16MachineDefinition.CX16Zeropage +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith +import kotlin.test.assertFalse +import kotlin.test.assertTrue + + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class TestC64Zeropage { + + private val errors = ErrorReporter() + + @Test + fun testNames() { + val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, C64Target)) + + zp.allocate("", DataType.UBYTE, null, errors) + zp.allocate("", DataType.UBYTE, null, errors) + zp.allocate("varname", DataType.UBYTE, null, errors) + assertFailsWith { + zp.allocate("varname", DataType.UBYTE, null, errors) + } + zp.allocate("varname2", DataType.UBYTE, null, errors) + } + + @Test + fun testZpFloatEnable() { + val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) + assertFailsWith { + zp.allocate("", DataType.FLOAT, null, errors) + } + val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, false, C64Target)) + assertFailsWith { + zp2.allocate("", DataType.FLOAT, null, errors) + } + val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false, C64Target)) + zp3.allocate("", DataType.FLOAT, null, errors) + } + + @Test + fun testZpModesWithFloats() { + C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) + C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, C64Target)) + C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, C64Target)) + C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false, C64Target)) + C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target)) + C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false, C64Target)) + assertFailsWith { + C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), true, false, C64Target)) + } + assertFailsWith { + C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true, false, C64Target)) + } + } + + @Test + fun testZpDontuse() { + val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, false, C64Target)) + println(zp.free) + assertEquals(0, zp.availableBytes()) + assertFailsWith { + zp.allocate("", DataType.BYTE, null, errors) + } + } + + @Test + fun testFreeSpacesBytes() { + val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target)) + assertEquals(18, zp1.availableBytes()) + val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false, C64Target)) + assertEquals(85, zp2.availableBytes()) + val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, C64Target)) + assertEquals(125, zp3.availableBytes()) + val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) + assertEquals(238, zp4.availableBytes()) + zp4.allocate("test", DataType.UBYTE, null, errors) + assertEquals(237, zp4.availableBytes()) + zp4.allocate("test2", DataType.UBYTE, null, errors) + assertEquals(236, zp4.availableBytes()) + } + + @Test + fun testFreeSpacesWords() { + val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target)) + assertEquals(6, zp1.availableWords()) + val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false, C64Target)) + assertEquals(38, zp2.availableWords()) + val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, C64Target)) + assertEquals(57, zp3.availableWords()) + val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) + assertEquals(116, zp4.availableWords()) + zp4.allocate("test", DataType.UWORD, null, errors) + assertEquals(115, zp4.availableWords()) + zp4.allocate("test2", DataType.UWORD, null, errors) + assertEquals(114, zp4.availableWords()) + } + + @Test + fun testReservedSpace() { + val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) + assertEquals(238, zp1.availableBytes()) + assertTrue(50 in zp1.free) + assertTrue(100 in zp1.free) + assertTrue(49 in zp1.free) + assertTrue(101 in zp1.free) + assertTrue(200 in zp1.free) + assertTrue(255 in zp1.free) + assertTrue(199 in zp1.free) + val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, listOf(50 .. 100, 200..255), false, false, C64Target)) + assertEquals(139, zp2.availableBytes()) + assertFalse(50 in zp2.free) + assertFalse(100 in zp2.free) + assertTrue(49 in zp2.free) + assertTrue(101 in zp2.free) + assertFalse(200 in zp2.free) + assertFalse(255 in zp2.free) + assertTrue(199 in zp2.free) + } + + @Test + fun testBasicsafeAllocation() { + val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target)) + assertEquals(18, zp.availableBytes()) + assertTrue(zp.hasByteAvailable()) + assertTrue(zp.hasWordAvailable()) + + assertFailsWith { + // in regular zp there aren't 5 sequential bytes free + zp.allocate("", DataType.FLOAT, null, errors) + } + + for (i in 0 until zp.availableBytes()) { + val loc = zp.allocate("", DataType.UBYTE, null, errors) + assertTrue(loc > 0) + } + assertEquals(0, zp.availableBytes()) + assertFalse(zp.hasByteAvailable()) + assertFalse(zp.hasWordAvailable()) + assertFailsWith { + zp.allocate("", DataType.UBYTE, null, errors) + } + assertFailsWith { + zp.allocate("", DataType.UWORD, null, errors) + } + } + + @Test + fun testFullAllocation() { + val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target)) + assertEquals(238, zp.availableBytes()) + assertTrue(zp.hasByteAvailable()) + assertTrue(zp.hasWordAvailable()) + val loc = zp.allocate("", DataType.UWORD, null, errors) + assertTrue(loc > 3) + assertFalse(loc in zp.free) + val num = zp.availableBytes() / 2 + + for(i in 0..num-4) { + zp.allocate("", DataType.UWORD, null, errors) + } + assertEquals(6,zp.availableBytes()) + + assertFailsWith { + // can't allocate because no more sequential bytes, only fragmented + zp.allocate("", DataType.UWORD, null, errors) + } + + for(i in 0..5) { + zp.allocate("", DataType.UBYTE, null, errors) + } + + assertEquals(0, zp.availableBytes()) + assertFalse(zp.hasByteAvailable()) + assertFalse(zp.hasWordAvailable()) + assertFailsWith { + // no more space + zp.allocate("", DataType.UBYTE, null, errors) + } + } + + @Test + fun testEfficientAllocation() { + val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target)) + assertEquals(18, zp.availableBytes()) + assertEquals(0x04, zp.allocate("", DataType.WORD, null, errors)) + assertEquals(0x06, zp.allocate("", DataType.UBYTE, null, errors)) + assertEquals(0x0a, zp.allocate("", DataType.UBYTE, null, errors)) + assertEquals(0x9b, zp.allocate("", DataType.UWORD, null, errors)) + assertEquals(0x9e, zp.allocate("", DataType.UWORD, null, errors)) + assertEquals(0xa5, zp.allocate("", DataType.UWORD, null, errors)) + assertEquals(0xb0, zp.allocate("", DataType.UWORD, null, errors)) + assertEquals(0xbe, zp.allocate("", DataType.UWORD, null, errors)) + assertEquals(0x0e, zp.allocate("", DataType.UBYTE, null, errors)) + assertEquals(0x92, zp.allocate("", DataType.UBYTE, null, errors)) + assertEquals(0x96, zp.allocate("", DataType.UBYTE, null, errors)) + assertEquals(0xf9, zp.allocate("", DataType.UBYTE, null, errors)) + assertEquals(0, zp.availableBytes()) + } + + @Test + fun testReservedLocations() { + val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, C64Target)) + assertEquals(zp.SCRATCH_REG, zp.SCRATCH_B1+1, "zp _B1 and _REG must be next to each other to create a word") + } +} + + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class TestCx16Zeropage { + private val errors = ErrorReporter() + + @Test + fun testReservedLocations() { + val zp = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, Cx16Target)) + assertEquals(zp.SCRATCH_REG, zp.SCRATCH_B1+1, "zp _B1 and _REG must be next to each other to create a word") + } + + @Test + fun testFreeSpacesBytes() { + val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, Cx16Target)) + assertEquals(88, zp1.availableBytes()) + val zp2 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, Cx16Target)) + assertEquals(175, zp2.availableBytes()) + val zp3 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, Cx16Target)) + assertEquals(216, zp3.availableBytes()) + zp3.allocate("test", DataType.UBYTE, null, errors) + assertEquals(215, zp3.availableBytes()) + zp3.allocate("test2", DataType.UBYTE, null, errors) + assertEquals(214, zp3.availableBytes()) + } + + @Test + fun testFreeSpacesWords() { + val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, Cx16Target)) + assertEquals(108, zp1.availableWords()) + val zp2 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, Cx16Target)) + assertEquals(87, zp2.availableWords()) + val zp3 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, Cx16Target)) + assertEquals(44, zp3.availableWords()) + zp3.allocate("test", DataType.UWORD, null, errors) + assertEquals(43, zp3.availableWords()) + zp3.allocate("test2", DataType.UWORD, null, errors) + assertEquals(42, zp3.availableWords()) + } + + @Test + fun testReservedSpace() { + val zp1 = CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, Cx16Target)) + assertEquals(216, zp1.availableBytes()) + assertTrue(0x22 in zp1.free) + assertTrue(0x80 in zp1.free) + assertTrue(0xff in zp1.free) + assertFalse(0x02 in zp1.free) + assertFalse(0x21 in zp1.free) + } +}