prog8/compiler/test/UnitTests.kt

583 lines
32 KiB
Kotlin
Raw Normal View History

2018-09-15 14:21:05 +00:00
package prog8tests
2018-08-10 00:58:41 +00:00
2018-08-16 23:47:07 +00:00
import org.hamcrest.MatcherAssert.assertThat
2018-08-30 21:07:50 +00:00
import org.hamcrest.Matchers.closeTo
2018-08-16 23:47:07 +00:00
import org.hamcrest.Matchers.equalTo
2018-08-10 00:58:41 +00:00
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
2019-07-13 01:16:48 +00:00
import prog8.compiler.target.c64.Petscii
import prog8.compiler.target.cx16.CX16MachineDefinition
2018-12-14 22:15:44 +00:00
import java.io.CharConversionException
2021-02-07 17:34:55 +00:00
import java.nio.file.Path
import kotlin.test.*
2018-08-10 00:58:41 +00:00
2018-08-16 23:47:07 +00:00
@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())
2018-10-13 14:09:10 +00:00
assertEquals("\$10", 16.toHex())
2018-08-16 23:47:07 +00:00
assertEquals("\$ff", 255.toHex())
2018-10-13 14:09:10 +00:00
assertEquals("\$0100", 256.toHex())
assertEquals("\$4e5c", 20060.toHex())
assertEquals("\$c382", 50050.toHex())
2018-08-16 23:47:07 +00:00
assertEquals("\$ffff", 65535.toHex())
assertEquals("\$ffff", 65535L.toHex())
2018-10-13 14:09:10 +00:00
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())
2021-02-07 05:21:29 +00:00
assertFailsWith<IllegalArgumentException> { 65536.toHex() }
assertFailsWith<IllegalArgumentException> { 65536L.toHex() }
2018-08-16 23:47:07 +00:00
}
@Test
fun testFloatToMflpt5() {
2018-08-30 21:07:50 +00:00
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)))
2018-08-16 23:47:07 +00:00
}
@Test
fun testFloatRange() {
2018-08-30 21:07:50 +00:00
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<CompilerException> { Mflpt5.fromNumber(1.7014118346e+38) }
assertFailsWith<CompilerException> { Mflpt5.fromNumber(-1.7014118346e+38) }
assertFailsWith<CompilerException> { Mflpt5.fromNumber(1.7014118347e+38) }
assertFailsWith<CompilerException> { Mflpt5.fromNumber(-1.7014118347e+38) }
2018-08-16 23:47:07 +00:00
}
2018-08-30 21:07:50 +00:00
@Test
fun testMflpt5ToFloat() {
val epsilon=0.000000001
2018-08-30 21:07:50 +00:00
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))
2018-08-30 21:07:50 +00:00
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))
2018-08-30 21:07:50 +00:00
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))
2018-08-30 21:07:50 +00:00
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))
2018-08-30 21:07:50 +00:00
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))
2018-08-30 21:07:50 +00:00
}
2018-08-16 23:47:07 +00:00
}
2018-08-10 00:58:41 +00:00
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class TestC64Zeropage {
2020-03-14 22:47:26 +00:00
private val errors = ErrorReporter()
2018-08-16 21:10:28 +00:00
@Test
fun testNames() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false, C64Target))
2018-08-16 21:10:28 +00:00
2020-03-14 22:47:26 +00:00
zp.allocate("", DataType.UBYTE, null, errors)
zp.allocate("", DataType.UBYTE, null, errors)
zp.allocate("varname", DataType.UBYTE, null, errors)
2018-08-16 21:10:28 +00:00
assertFailsWith<AssertionError> {
2020-03-14 22:47:26 +00:00
zp.allocate("varname", DataType.UBYTE, null, errors)
2018-08-16 21:10:28 +00:00
}
2020-03-14 22:47:26 +00:00
zp.allocate("varname2", DataType.UBYTE, null, errors)
2018-08-16 21:10:28 +00:00
}
@Test
fun testZpFloatEnable() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target))
2018-08-16 23:47:07 +00:00
assertFailsWith<CompilerException> {
2020-03-14 22:47:26 +00:00
zp.allocate("", DataType.FLOAT, null, errors)
2018-08-16 21:10:28 +00:00
}
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), true, false, C64Target))
assertFailsWith<CompilerException> {
2020-03-14 22:47:26 +00:00
zp2.allocate("", DataType.FLOAT, null, errors)
}
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), true, false, C64Target))
2020-03-14 22:47:26 +00:00
zp3.allocate("", DataType.FLOAT, null, errors)
2018-08-16 21:10:28 +00:00
}
@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<CompilerException> {
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), true, false, C64Target))
}
assertFailsWith<CompilerException> {
C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true, false, C64Target))
}
}
2019-08-11 19:30:13 +00:00
@Test
fun testZpDontuse() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, false, C64Target))
2019-08-11 19:30:13 +00:00
println(zp.free)
assertEquals(0, zp.available())
assertFailsWith<CompilerException> {
2020-03-14 22:47:26 +00:00
zp.allocate("", DataType.BYTE, null, errors)
2019-08-11 19:30:13 +00:00
}
}
2018-08-16 21:10:28 +00:00
@Test
fun testFreeSpaces() {
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target))
assertEquals(18, zp1.available())
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), false, false, C64Target))
assertEquals(89, zp2.available())
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), false, false, C64Target))
assertEquals(125, zp3.available())
val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target))
assertEquals(238, zp4.available())
}
2018-10-08 22:01:53 +00:00
@Test
fun testReservedSpace() {
val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target))
2018-12-07 23:27:12 +00:00
assertEquals(238, zp1.available())
2018-10-08 22:01:53 +00:00
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))
2018-10-08 22:01:53 +00:00
assertEquals(139, zp2.available())
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.available())
2019-01-27 00:02:45 +00:00
assertFailsWith<ZeropageDepletedError> {
// in regular zp there aren't 5 sequential bytes free
2020-03-14 22:47:26 +00:00
zp.allocate("", DataType.FLOAT, null, errors)
2018-08-16 21:10:28 +00:00
}
2018-08-16 21:10:28 +00:00
for (i in 0 until zp.available()) {
2020-03-14 22:47:26 +00:00
val loc = zp.allocate("", DataType.UBYTE, null, errors)
assertTrue(loc > 0)
2018-08-16 21:10:28 +00:00
}
assertEquals(0, zp.available())
2019-01-27 00:02:45 +00:00
assertFailsWith<ZeropageDepletedError> {
2020-03-14 22:47:26 +00:00
zp.allocate("", DataType.UBYTE, null, errors)
2018-08-16 21:10:28 +00:00
}
2019-01-27 00:02:45 +00:00
assertFailsWith<ZeropageDepletedError> {
2020-03-14 22:47:26 +00:00
zp.allocate("", DataType.UWORD, null, errors)
2018-08-16 21:10:28 +00:00
}
}
2018-08-10 00:58:41 +00:00
@Test
2018-08-16 21:10:28 +00:00
fun testFullAllocation() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), false, false, C64Target))
2018-12-07 23:27:12 +00:00
assertEquals(238, zp.available())
2020-03-14 22:47:26 +00:00
val loc = zp.allocate("", DataType.UWORD, null, errors)
assertTrue(loc > 3)
2018-09-30 12:19:41 +00:00
assertFalse(loc in zp.free)
val num = zp.available() / 2
2018-08-16 21:10:28 +00:00
2018-12-16 02:38:17 +00:00
for(i in 0..num-4) {
2020-03-14 22:47:26 +00:00
zp.allocate("", DataType.UWORD, null, errors)
2018-08-16 21:10:28 +00:00
}
assertEquals(6,zp.available())
2018-08-16 21:10:28 +00:00
2019-01-27 00:02:45 +00:00
assertFailsWith<ZeropageDepletedError> {
2018-08-16 21:10:28 +00:00
// can't allocate because no more sequential bytes, only fragmented
2020-03-14 22:47:26 +00:00
zp.allocate("", DataType.UWORD, null, errors)
2018-08-16 21:10:28 +00:00
}
for(i in 0..5) {
2020-03-14 22:47:26 +00:00
zp.allocate("", DataType.UBYTE, null, errors)
2018-08-16 21:10:28 +00:00
}
assertEquals(0, zp.available())
2019-01-27 00:02:45 +00:00
assertFailsWith<ZeropageDepletedError> {
2018-08-16 21:10:28 +00:00
// no more space
2020-03-14 22:47:26 +00:00
zp.allocate("", DataType.UBYTE, null, errors)
2018-08-16 21:10:28 +00:00
}
2018-08-10 00:58:41 +00:00
}
@Test
2018-08-16 21:10:28 +00:00
fun testEfficientAllocation() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true, false, C64Target))
assertEquals(18, zp.available())
2020-03-14 22:47:26 +00:00
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))
2020-03-14 22:47:26 +00:00
assertEquals(0x0e, zp.allocate("", DataType.UBYTE, null, errors))
assertEquals(0x92, zp.allocate("", DataType.UBYTE, null, errors))
assertEquals(0x96, zp.allocate("", DataType.UBYTE, null, errors))
2020-03-14 22:47:26 +00:00
assertEquals(0xf9, zp.allocate("", DataType.UBYTE, null, errors))
assertEquals(0, zp.available())
2018-08-10 00:58:41 +00:00
}
@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 {
@Test
fun testReservedLocations() {
val zp = CX16MachineDefinition.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")
}
// TODO way more tests for the Cx16 zeropage?
2018-08-10 00:58:41 +00:00
}
2018-08-31 16:32:33 +00:00
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class TestPetscii {
@Test
fun testZero() {
assertThat(Petscii.encodePetscii("\u0000", true), equalTo(listOf<Short>(0)))
assertThat(Petscii.encodePetscii("\u0000", false), equalTo(listOf<Short>(0)))
assertThat(Petscii.decodePetscii(listOf(0), true), equalTo("\u0000"))
assertThat(Petscii.decodePetscii(listOf(0), false), equalTo("\u0000"))
}
2018-08-31 16:32:33 +00:00
@Test
fun testLowercase() {
assertThat(Petscii.encodePetscii("hello WORLD 123 @!£", true), equalTo(
2018-09-02 17:20:06 +00:00
listOf<Short>(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<Short>(0x12))) // reverse vid
assertThat(Petscii.encodePetscii("", true), equalTo(listOf<Short>(0xfa)))
2018-12-14 22:15:44 +00:00
assertFailsWith<CharConversionException> { Petscii.encodePetscii("π", true) }
assertFailsWith<CharConversionException> { Petscii.encodePetscii("", true) }
2018-08-31 16:32:33 +00:00
2018-09-02 09:54:42 +00:00
assertThat(Petscii.decodePetscii(listOf(72, 0xd7, 0x5c, 0xfa, 0x12), true), equalTo("hW£✓\uF11A"))
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodePetscii(listOf(-1), true) }
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodePetscii(listOf(256), true) }
2018-08-31 16:32:33 +00:00
}
@Test
fun testUppercase() {
assertThat(Petscii.encodePetscii("HELLO 123 @!£"), equalTo(
2018-09-02 17:20:06 +00:00
listOf<Short>(72, 69, 76, 76, 79, 32, 49, 50, 51, 32, 64, 33, 0x5c)))
assertThat(Petscii.encodePetscii("\uf11a"), equalTo(listOf<Short>(0x12))) // reverse vid
assertThat(Petscii.encodePetscii(""), equalTo(listOf<Short>(0xd3)))
assertThat(Petscii.encodePetscii("π"), equalTo(listOf<Short>(0xff)))
2018-12-14 22:15:44 +00:00
assertFailsWith<CharConversionException> { Petscii.encodePetscii("") }
2018-08-31 16:32:33 +00:00
2018-09-02 09:54:42 +00:00
assertThat(Petscii.decodePetscii(listOf(72, 0x5c, 0xd3, 0xff)), equalTo("H£♥π"))
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodePetscii(listOf(-1)) }
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodePetscii(listOf(256)) }
2018-08-31 16:32:33 +00:00
}
@Test
fun testScreencodeLowercase() {
assertThat(Petscii.encodeScreencode("hello WORLD 123 @!£", true), equalTo(
2018-09-02 17:20:06 +00:00
listOf<Short>(0x08, 0x05, 0x0c, 0x0c, 0x0f, 0x20, 0x57, 0x4f, 0x52, 0x4c, 0x44, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c)
2018-08-31 16:32:33 +00:00
))
2018-09-02 17:20:06 +00:00
assertThat(Petscii.encodeScreencode("", true), equalTo(listOf<Short>(0x7a)))
2018-12-14 22:15:44 +00:00
assertFailsWith<CharConversionException> { Petscii.encodeScreencode("", true) }
assertFailsWith<CharConversionException> { Petscii.encodeScreencode("π", true) }
2018-08-31 16:32:33 +00:00
2018-09-02 09:54:42 +00:00
assertThat(Petscii.decodeScreencode(listOf(0x08, 0x57, 0x1c, 0x7a), true), equalTo("hW£✓"))
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodeScreencode(listOf(-1), true) }
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodeScreencode(listOf(256), true) }
2018-08-31 16:32:33 +00:00
}
@Test
fun testScreencodeUppercase() {
assertThat(Petscii.encodeScreencode("WORLD 123 @!£"), equalTo(
2018-09-02 17:20:06 +00:00
listOf<Short>(0x17, 0x0f, 0x12, 0x0c, 0x04, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c)))
assertThat(Petscii.encodeScreencode(""), equalTo(listOf<Short>(0x53)))
assertThat(Petscii.encodeScreencode("π"), equalTo(listOf<Short>(0x5e)))
2018-12-14 22:15:44 +00:00
assertFailsWith<CharConversionException> { Petscii.encodeScreencode("") }
assertFailsWith<CharConversionException> { Petscii.encodeScreencode("hello") }
2018-08-31 16:32:33 +00:00
2018-09-02 09:54:42 +00:00
assertThat(Petscii.decodeScreencode(listOf(0x17, 0x1c, 0x53, 0x5e)), equalTo("W£♥π"))
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodeScreencode(listOf(-1)) }
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodeScreencode(listOf(256)) }
2018-08-31 16:32:33 +00:00
}
@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)
}
2018-08-31 16:32:33 +00:00
}
class TestMemory {
2021-02-07 17:34:55 +00:00
private class DummyFunctions: IBuiltinFunctions {
override val names: Set<String> = emptySet()
2021-02-09 00:47:05 +00:00
override val purefunctionNames: Set<String> = emptySet()
override fun constValue(name: String, args: List<Expression>, position: Position, memsizer: IMemSizer): NumericLiteralValue? = null
2021-02-07 17:34:55 +00:00
override fun returnType(name: String, args: MutableList<Expression>) = 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())
2021-02-09 17:38:44 +00:00
assertTrue(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
2021-02-09 17:38:44 +00:00
assertTrue(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0x9fff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
2021-02-09 17:38:44 +00:00
assertTrue(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0xc000, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
2021-02-09 17:38:44 +00:00
assertTrue(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0xcfff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
2021-02-09 17:38:44 +00:00
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())
2021-02-09 17:38:44 +00:00
assertFalse(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0xafff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
2021-02-09 17:38:44 +00:00
assertFalse(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0xd000, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
2021-02-09 17:38:44 +00:00
assertFalse(C64Target.isInRegularRAM(target, program))
memexpr = NumericLiteralValue.optimalInteger(0xffff, Position.DUMMY)
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
2021-02-09 17:38:44 +00:00
assertFalse(C64Target.isInRegularRAM(target, program))
}
@Test
fun testInValidRamC64_memory_identifiers() {
var target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.VAR)
val program = Program("test", mutableListOf(), DummyFunctions(), DummyMemsizer())
2021-02-07 17:34:55 +00:00
2021-02-09 17:38:44 +00:00
assertTrue(C64Target.isInRegularRAM(target, program))
target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.VAR)
2021-02-09 17:38:44 +00:00
assertFalse(C64Target.isInRegularRAM(target, program))
target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.CONST)
2021-02-09 17:38:44 +00:00
assertTrue(C64Target.isInRegularRAM(target, program))
target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.CONST)
2021-02-09 17:38:44 +00:00
assertFalse(C64Target.isInRegularRAM(target, program))
target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.MEMORY)
2021-02-09 17:38:44 +00:00
assertFalse(C64Target.isInRegularRAM(target, program))
}
@Test
private fun createTestProgramForMemoryRefViaVar(address: Int, vartype: VarDeclType): AssignTarget {
val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), 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)
2021-02-07 17:34:55 +00:00
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())
2021-02-09 17:38:44 +00:00
assertFalse(C64Target.isInRegularRAM(target, program))
}
@Test
fun testInValidRamC64_variable() {
val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, null, 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)
2021-02-07 17:34:55 +00:00
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
2021-02-07 17:34:55 +00:00
module.linkParents(ParentSentinel)
2021-02-09 17:38:44 +00:00
assertTrue(C64Target.isInRegularRAM(target, program))
}
@Test
fun testInValidRamC64_memmap_variable() {
val address = 0x1000
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), 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)
2021-02-07 17:34:55 +00:00
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
2021-02-07 17:34:55 +00:00
module.linkParents(ParentSentinel)
2021-02-09 17:38:44 +00:00
assertTrue(C64Target.isInRegularRAM(target, program))
}
@Test
fun testNotInValidRamC64_memmap_variable() {
val address = 0xd020
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), 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)
2021-02-07 17:34:55 +00:00
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
2021-02-07 17:34:55 +00:00
module.linkParents(ParentSentinel)
2021-02-09 17:38:44 +00:00
assertFalse(C64Target.isInRegularRAM(target, program))
}
@Test
fun testInValidRamC64_array() {
val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, null, 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)
2021-02-07 17:34:55 +00:00
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
2021-02-07 17:34:55 +00:00
module.linkParents(ParentSentinel)
2021-02-09 17:38:44 +00:00
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", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), 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)
2021-02-07 17:34:55 +00:00
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
2021-02-07 17:34:55 +00:00
module.linkParents(ParentSentinel)
2021-02-09 17:38:44 +00:00
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", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), 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)
2021-02-07 17:34:55 +00:00
val module = Module("test", mutableListOf(subroutine), Position.DUMMY, false, Path.of(""))
val program = Program("test", mutableListOf(module), DummyFunctions(), DummyMemsizer())
2021-02-07 17:34:55 +00:00
module.linkParents(ParentSentinel)
2021-02-09 17:38:44 +00:00
assertFalse(C64Target.isInRegularRAM(target, program))
}
}