converting compiler module's testcases to kotest assertions

This commit is contained in:
Irmen de Jong 2021-11-08 15:50:29 +01:00
parent 613efcacc7
commit 7961a09d16
14 changed files with 488 additions and 444 deletions

View File

@ -25,8 +25,6 @@ dependencies {
implementation "com.michael-bull.kotlin-result:kotlin-result-jvm:1.1.12"
testImplementation 'io.kotest:kotest-runner-junit5-jvm:4.6.3'
testImplementation "org.jetbrains.kotlin:kotlin-test-junit5"
testImplementation 'org.hamcrest:hamcrest:2.2'
}
configurations.all {

View File

@ -12,9 +12,7 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
<orderEntry type="module" module-name="compilerAst" />
<orderEntry type="library" name="hamcrest" level="project" />
<orderEntry type="library" name="jetbrains.kotlinx.cli.jvm" level="project" />
<orderEntry type="library" name="junit.jupiter" level="project" />
<orderEntry type="library" name="michael.bull.kotlin.result.jvm" level="project" />
<orderEntry type="module" module-name="codeOptimizers" />
<orderEntry type="module" module-name="compilerInterfaces" />

View File

@ -2,10 +2,6 @@ package prog8tests
import com.github.michaelbull.result.getErrorOrElse
import com.github.michaelbull.result.getOrElse
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
import org.hamcrest.Matchers.nullValue
import org.hamcrest.core.Is
import prog8.ast.Program
import prog8.ast.internedStringsModuleName
import prog8.compiler.ModuleImporter
@ -67,26 +63,22 @@ class TestModuleImporter: FunSpec({
val srcPathRel = assumeNotExists(dirRel, "i_do_not_exist")
val srcPathAbs = srcPathRel.absolute()
val error1 = importer.importModule(srcPathRel).getErrorOrElse { fail("should have import error") }
assertThat(
".file should be normalized",
"${error1.file}", equalTo("${error1.file.normalize()}")
)
assertThat(
".file should point to specified path",
error1.file.absolutePath, equalTo("${srcPathAbs.normalize()}")
)
assertThat(program.modules.size, equalTo(1))
withClue(".file should be normalized") {
"${error1.file}" shouldBe "${error1.file.normalize()}"
}
withClue(".file should point to specified path") {
error1.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
}
program.modules.size shouldBe 1
val error2 = importer.importModule(srcPathAbs).getErrorOrElse { fail("should have import error") }
assertThat(
".file should be normalized",
"${error2.file}", equalTo("${error2.file.normalize()}")
)
assertThat(
".file should point to specified path",
error2.file.absolutePath, equalTo("${srcPathAbs.normalize()}")
)
assertThat(program.modules.size, equalTo(1))
withClue(".file should be normalized") {
"${error2.file}" shouldBe "${error2.file.normalize()}"
}
withClue(".file should point to specified path") {
error2.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
}
program.modules.size shouldBe 1
}
test("testDirectory") {
@ -97,29 +89,25 @@ class TestModuleImporter: FunSpec({
shouldThrow<AccessDeniedException> { importer.importModule(srcPathRel) }
.let {
assertThat(
".file should be normalized",
"${it.file}", equalTo("${it.file.normalize()}")
)
assertThat(
".file should point to specified path",
it.file.absolutePath, equalTo("${srcPathAbs.normalize()}")
)
withClue(".file should be normalized") {
"${it.file}" shouldBe "${it.file.normalize()}"
}
withClue(".file should point to specified path") {
it.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
}
}
assertThat(program.modules.size, equalTo(1))
program.modules.size shouldBe 1
shouldThrow<AccessDeniedException> { importer.importModule(srcPathAbs) }
.let {
assertThat(
".file should be normalized",
"${it.file}", equalTo("${it.file.normalize()}")
)
assertThat(
".file should point to specified path",
it.file.absolutePath, equalTo("${srcPathAbs.normalize()}")
)
withClue(".file should be normalized") {
"${it.file}" shouldBe "${it.file.normalize()}"
}
withClue(".file should point to specified path") {
it.file.absolutePath shouldBe "${srcPathAbs.normalize()}"
}
}
assertThat(program.modules.size, equalTo(1))
program.modules.size shouldBe 1
}
}
@ -134,9 +122,9 @@ class TestModuleImporter: FunSpec({
val path = assumeReadableFile(searchIn[0], fileName)
val module = importer.importModule(path.absolute()).getOrElse { throw it }
assertThat(program.modules.size, equalTo(2))
program.modules.size shouldBe 2
module shouldBeIn program.modules
assertThat(module.program, equalTo(program))
module.program shouldBe program
}
test("testRelativeToWorkingDir") {
@ -146,12 +134,14 @@ class TestModuleImporter: FunSpec({
val importer = makeImporter(null, searchIn)
val fileName = "simple_main.p8"
val path = assumeReadableFile(searchIn[0], fileName)
assertThat("sanity check: path should NOT be absolute", path.isAbsolute, equalTo(false))
withClue("sanity check: path should NOT be absolute") {
path.isAbsolute shouldBe false
}
val module = importer.importModule(path).getOrElse { throw it }
assertThat(program.modules.size, equalTo(2))
program.modules.size shouldBe 2
module shouldBeIn program.modules
assertThat(module.program, equalTo(program))
module.program shouldBe program
}
test("testRelativeTo1stDirInSearchList") {
@ -164,9 +154,9 @@ class TestModuleImporter: FunSpec({
assumeReadableFile(searchIn, path)
val module = importer.importModule(path).getOrElse { throw it }
assertThat(program.modules.size, equalTo(2))
program.modules.size shouldBe 2
module shouldBeIn program.modules
assertThat(module.program, equalTo(program))
module.program shouldBe program
}
//Disabled("TODO: relative to 2nd in search list")
@ -185,13 +175,13 @@ class TestModuleImporter: FunSpec({
repeat(2) { n -> withClue(count[n] + " call") {
shouldThrow<ParseError>() { act() }.let {
assertThat(it.position.file, equalTo(SourceCode.relative(srcPath).toString()))
assertThat("line; should be 1-based", it.position.line, equalTo(2))
assertThat("startCol; should be 0-based", it.position.startCol, equalTo(6))
assertThat("endCol; should be 0-based", it.position.endCol, equalTo(6))
it.position.file shouldBe SourceCode.relative(srcPath).toString()
withClue("line; should be 1-based") { it.position.line shouldBe 2 }
withClue("startCol; should be 0-based") { it.position.startCol shouldBe 6 }
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
}
}
assertThat(program.modules.size, equalTo(1))
program.modules.size shouldBe 1
}
}
@ -205,14 +195,14 @@ class TestModuleImporter: FunSpec({
repeat(repetitions) { n -> withClue(count[n] + " call") {
shouldThrow<ParseError>() { act() }.let {
assertThat(it.position.file, equalTo(SourceCode.relative(imported).toString()))
assertThat("line; should be 1-based", it.position.line, equalTo(2))
assertThat("startCol; should be 0-based", it.position.startCol, equalTo(6))
assertThat("endCol; should be 0-based", it.position.endCol, equalTo(6))
it.position.file shouldBe SourceCode.relative(imported).toString()
withClue("line; should be 1-based") { it.position.line shouldBe 2 }
withClue("startCol; should be 0-based") { it.position.startCol shouldBe 6 }
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
}
}
assertThat("imported module with error in it should not be present", program.modules.size, equalTo(1))
assertThat(program.modules[0].name, equalTo(internedStringsModuleName))
withClue("imported module with error in it should not be present") { program.modules.size shouldBe 1 }
program.modules[0].name shouldBe internedStringsModuleName
}
}
@ -238,22 +228,18 @@ class TestModuleImporter: FunSpec({
repeat(2) { n ->
val result = importer.importLibraryModule(filenameNoExt)
assertThat(count[n] + " call / NO .p8 extension", result, Is(nullValue()))
withClue(count[n] + " call / NO .p8 extension") {
errors.noErrors() shouldBe false
}
withClue(count[n] + " call / NO .p8 extension") { result shouldBe null }
withClue(count[n] + " call / NO .p8 extension") { errors.noErrors() shouldBe false }
errors.errors.single() shouldContain "0:0: no module found with name i_do_not_exist"
errors.report()
assertThat(program.modules.size, equalTo(1))
program.modules.size shouldBe 1
val result2 = importer.importLibraryModule(filenameWithExt)
assertThat(count[n] + " call / with .p8 extension", result2, Is(nullValue()))
withClue(count[n] + " call / with .p8 extension") {
importer.errors.noErrors() shouldBe false
}
withClue(count[n] + " call / with .p8 extension") { result2 shouldBe null }
withClue(count[n] + " call / with .p8 extension") { importer.errors.noErrors() shouldBe false }
errors.errors.single() shouldContain "0:0: no module found with name i_do_not_exist.p8"
errors.report()
assertThat(program.modules.size, equalTo(1))
program.modules.size shouldBe 1
}
}
}
@ -269,13 +255,13 @@ class TestModuleImporter: FunSpec({
shouldThrow<ParseError>()
{
importer.importLibraryModule(srcPath.nameWithoutExtension) }.let {
assertThat(it.position.file, equalTo(SourceCode.relative(srcPath).toString()))
assertThat("line; should be 1-based", it.position.line, equalTo(2))
assertThat("startCol; should be 0-based", it.position.startCol, equalTo(6))
assertThat("endCol; should be 0-based", it.position.endCol, equalTo(6))
it.position.file shouldBe SourceCode.relative(srcPath).toString()
withClue("line; should be 1-based") { it.position.line shouldBe 2 }
withClue("startCol; should be 0-based") { it.position.startCol shouldBe 6 }
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
}
}
assertThat(program.modules.size, equalTo(1))
program.modules.size shouldBe 1
}
}
@ -291,14 +277,14 @@ class TestModuleImporter: FunSpec({
repeat(repetitions) { n -> withClue(count[n] + " call") {
shouldThrow<ParseError>() {
act() }.let {
assertThat(it.position.file, equalTo(SourceCode.relative(imported).toString()))
assertThat("line; should be 1-based", it.position.line, equalTo(2))
assertThat("startCol; should be 0-based", it.position.startCol, equalTo(6))
assertThat("endCol; should be 0-based", it.position.endCol, equalTo(6))
it.position.file shouldBe SourceCode.relative(imported).toString()
withClue("line; should be 1-based") { it.position.line shouldBe 2 }
withClue("startCol; should be 0-based") { it.position.startCol shouldBe 6 }
withClue("endCol; should be 0-based") { it.position.endCol shouldBe 6 }
}
}
assertThat("imported module with error in it should not be present", program.modules.size, equalTo(1))
assertThat(program.modules[0].name, equalTo(internedStringsModuleName))
withClue("imported module with error in it should not be present") { program.modules.size shouldBe 1 }
program.modules[0].name shouldBe internedStringsModuleName
importer.errors.report()
}
}

View File

@ -1,10 +1,10 @@
package prog8tests
import io.kotest.assertions.fail
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.instanceOf
import org.junit.jupiter.api.Assertions.fail
import prog8.ast.IFunctionCall
import prog8.ast.base.DataType
import prog8.ast.base.VarDeclType

View File

@ -1,6 +1,9 @@
package prog8tests
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import prog8.ast.expressions.AddressOf
import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.StringLiteralValue
@ -12,8 +15,6 @@ import prog8tests.helpers.assertFailure
import prog8tests.helpers.assertSuccess
import prog8tests.helpers.compileFile
import kotlin.io.path.name
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
/**
@ -40,10 +41,10 @@ class TestCompilerOnImportsAndIncludes: FunSpec({
.map { it.args[0] as IdentifierReference }
.map { it.targetVarDecl(program)!!.value as StringLiteralValue }
assertEquals("main.bar", strLits[0].value)
assertEquals("foo.bar", strLits[1].value)
assertEquals("main", strLits[0].definingScope.name)
assertEquals("foo", strLits[1].definingScope.name)
strLits[0].value shouldBe "main.bar"
strLits[1].value shouldBe "foo.bar"
strLits[0].definingScope.name shouldBe "main"
strLits[1].definingScope.name shouldBe "foo"
}
}
@ -63,13 +64,13 @@ class TestCompilerOnImportsAndIncludes: FunSpec({
.map { it.args[0] }
val str0 = (args[0] as IdentifierReference).targetVarDecl(program)!!.value as StringLiteralValue
assertEquals("main.bar", str0.value)
assertEquals("main", str0.definingScope.name)
str0.value shouldBe "main.bar"
str0.definingScope.name shouldBe "main"
val id1 = (args[1] as AddressOf).identifier
val lbl1 = id1.targetStatement(program) as Label
assertEquals("foo_bar", lbl1.name)
assertEquals("start", lbl1.definingScope.name)
lbl1.name shouldBe "foo_bar"
lbl1.definingScope.name shouldBe "start"
}
}
@ -100,11 +101,11 @@ class TestCompilerOnImportsAndIncludes: FunSpec({
test("%asmbinary from ${where}folder") {
val p8Path = assumeReadableFile(fixturesDir, p8Str)
// val binPath = assumeReadableFile(fixturesDir, binStr)
assertNotEquals( // the bug we're testing for (#54) was hidden if outputDir == workingDir
workingDir.normalize().toAbsolutePath(),
outputDir.normalize().toAbsolutePath(),
"sanity check: workingDir and outputDir should not be the same folder"
)
// the bug we're testing for (#54) was hidden if outputDir == workingDir
withClue("sanity check: workingDir and outputDir should not be the same folder") {
outputDir.normalize().toAbsolutePath() shouldNotBe workingDir.normalize().toAbsolutePath()
}
compileFile(Cx16Target, false, p8Path.parent, p8Path.name, outputDir)
.assertSuccess(

View File

@ -1,6 +1,9 @@
package prog8tests
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
import prog8.ast.base.DataType
import prog8.ast.base.Position
import prog8.ast.expressions.*
@ -15,8 +18,6 @@ import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.assertFailure
import prog8tests.helpers.assertSuccess
import prog8tests.helpers.compileText
import kotlin.test.assertContains
import kotlin.test.assertEquals
/**
@ -49,8 +50,12 @@ class TestCompilerOnRanges: FunSpec({
val expectedStr = "$expectedStart .. $expectedEnd"
val actualStr = "${rhsValues.first()} .. ${rhsValues.last()}"
assertEquals(expectedStr, actualStr,".first .. .last")
assertEquals(expectedEnd - expectedStart + 1, rhsValues.last() - rhsValues.first() + 1, "rangeExpr.size()")
withClue(".first .. .last") {
actualStr shouldBe expectedStr
}
withClue("rangeExpr.size()") {
(rhsValues.last() - rhsValues.first() + 1) shouldBe (expectedEnd - expectedStart + 1)
}
}
test("testFloatArrayInitializerWithRange_char_to_char") {
@ -77,8 +82,12 @@ class TestCompilerOnRanges: FunSpec({
val expectedStr = "$expectedStart .. $expectedEnd"
val actualStr = "${rhsValues.first()} .. ${rhsValues.last()}"
assertEquals(expectedStr, actualStr,".first .. .last")
assertEquals(expectedEnd - expectedStart + 1, rhsValues.size, "rangeExpr.size()")
withClue(".first .. .last") {
actualStr shouldBe expectedStr
}
withClue("rangeExpr.size()") {
rhsValues.size shouldBe (expectedEnd - expectedStart + 1)
}
}
context("floatArrayInitializerWithRange") {
@ -145,8 +154,12 @@ class TestCompilerOnRanges: FunSpec({
val intProgression = rangeExpr.toConstantIntegerRange()
val actualStr = "${intProgression?.first} .. ${intProgression?.last}"
assertEquals(expectedStr, actualStr,".first .. .last")
assertEquals(expectedEnd - expectedStart + 1, rangeExpr.size(), "rangeExpr.size()")
withClue(".first .. .last") {
actualStr shouldBe expectedStr
}
withClue("rangeExpr.size()") {
rangeExpr.size() shouldBe (expectedEnd - expectedStart + 1)
}
}
test("testForLoopWithRange_bool_to_bool") {
@ -169,10 +182,10 @@ class TestCompilerOnRanges: FunSpec({
.map { it.iterable }
.filterIsInstance<RangeExpr>()[0]
assertEquals(2, rangeExpr.size())
rangeExpr.size() shouldBe 2
val intProgression = rangeExpr.toConstantIntegerRange()
assertEquals(0, intProgression?.first)
assertEquals(1, intProgression?.last)
intProgression?.first shouldBe 0
intProgression?.last shouldBe 1
}
test("testForLoopWithRange_ubyte_to_ubyte") {
@ -195,10 +208,10 @@ class TestCompilerOnRanges: FunSpec({
.map { it.iterable }
.filterIsInstance<RangeExpr>()[0]
assertEquals(9, rangeExpr.size())
rangeExpr.size() shouldBe 9
val intProgression = rangeExpr.toConstantIntegerRange()
assertEquals(1, intProgression?.first)
assertEquals(9, intProgression?.last)
intProgression?.first shouldBe 1
intProgression?.last shouldBe 9
}
test("testForLoopWithRange_str_downto_str") {
@ -213,9 +226,9 @@ class TestCompilerOnRanges: FunSpec({
}
}
""", errors, false).assertFailure()
assertEquals(2, errors.errors.size)
assertContains(errors.errors[0], ".p8:5:29: range expression from value must be integer")
assertContains(errors.errors[1], ".p8:5:44: range expression to value must be integer")
errors.errors.size shouldBe 2
errors.errors[0] shouldContain ".p8:5:29: range expression from value must be integer"
errors.errors[1] shouldContain ".p8:5:44: range expression to value must be integer"
}
test("testForLoopWithIterable_str") {
@ -237,7 +250,7 @@ class TestCompilerOnRanges: FunSpec({
.map { it.iterable }
.filterIsInstance<IdentifierReference>()[0]
assertEquals(DataType.STR, iterable.inferType(program).getOr(DataType.UNDEFINED))
iterable.inferType(program).getOr(DataType.UNDEFINED) shouldBe DataType.STR
}
test("testRangeExprNumericSize") {
@ -246,7 +259,7 @@ class TestCompilerOnRanges: FunSpec({
NumericLiteralValue.optimalInteger(20, Position.DUMMY),
NumericLiteralValue.optimalInteger(2, Position.DUMMY),
Position.DUMMY)
assertEquals(6, expr.size())
expr.size() shouldBe 6
expr.toConstantIntegerRange()
}
})

View File

@ -1,6 +1,9 @@
package prog8tests
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldStartWith
import prog8.ast.internedStringsModuleName
import prog8.compiler.determineCompilationOptions
import prog8.compiler.parseImports
@ -10,8 +13,6 @@ import prog8tests.ast.helpers.outputDir
import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.assertSuccess
import prog8tests.helpers.compileText
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class TestImportedModulesOrderAndOptions: FunSpec({
@ -27,21 +28,24 @@ main {
}
}
""").assertSuccess()
assertTrue(result.program.toplevelModule.name.startsWith("on_the_fly_test"))
result.program.toplevelModule.name shouldStartWith "on_the_fly_test"
val moduleNames = result.program.modules.map { it.name }
assertTrue(moduleNames[0].startsWith("on_the_fly_test"), "main module must be first")
assertEquals(listOf(
"prog8_interned_strings",
"textio",
"syslib",
"conv",
"floats",
"math",
"prog8_lib"
), moduleNames.drop(1), "module order in parse tree")
assertTrue(result.program.toplevelModule.name.startsWith("on_the_fly_test"))
withClue("main module must be first") {
moduleNames[0] shouldStartWith "on_the_fly_test"
}
withClue("module order in parse tree") {
moduleNames.drop(1) shouldBe listOf(
"prog8_interned_strings",
"textio",
"syslib",
"conv",
"floats",
"math",
"prog8_lib"
)
}
result.program.toplevelModule.name shouldStartWith "on_the_fly_test"
}
test("testCompilationOptionsCorrectFromMain") {
@ -57,11 +61,11 @@ main {
}
}
""").assertSuccess()
assertTrue(result.program.toplevelModule.name.startsWith("on_the_fly_test"))
result.program.toplevelModule.name shouldStartWith "on_the_fly_test"
val options = determineCompilationOptions(result.program, C64Target)
assertTrue(options.floats)
assertEquals(ZeropageType.DONTUSE, options.zeropage)
assertTrue(options.noSysInit)
options.floats shouldBe true
options.zeropage shouldBe ZeropageType.DONTUSE
options.noSysInit shouldBe true
}
test("testModuleOrderAndCompilationOptionsCorrectWithJustImports") {
@ -83,16 +87,23 @@ main {
filepath.toFile().writeText(sourceText)
val (program, options, importedfiles) = parseImports(filepath, errors, C64Target, emptyList())
assertEquals(filenameBase, program.toplevelModule.name)
assertEquals(1, importedfiles.size, "all imports other than the test source must have been internal resources library files")
assertEquals(listOf(
internedStringsModuleName,
filenameBase,
"textio", "syslib", "conv", "floats", "math", "prog8_lib"
), program.modules.map {it.name}, "module order in parse tree")
assertTrue(options.floats)
assertEquals(ZeropageType.DONTUSE, options.zeropage, "zeropage option must be correctly taken from main module, not from float module import logic")
assertTrue(options.noSysInit)
program.toplevelModule.name shouldBe filenameBase
withClue("all imports other than the test source must have been internal resources library files") {
importedfiles.size shouldBe 1
}
withClue("module order in parse tree") {
program.modules.map { it.name } shouldBe
listOf(
internedStringsModuleName,
filenameBase,
"textio", "syslib", "conv", "floats", "math", "prog8_lib"
)
}
options.floats shouldBe true
options.noSysInit shouldBe true
withClue("zeropage option must be correctly taken from main module, not from float module import logic") {
options.zeropage shouldBe ZeropageType.DONTUSE
}
}
})

View File

@ -1,16 +1,14 @@
package prog8tests
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import prog8.ast.base.DataType
import prog8.ast.base.Position
import prog8.ast.expressions.ArrayLiteralValue
import prog8.ast.expressions.InferredTypes
import prog8.ast.expressions.NumericLiteralValue
import prog8.ast.expressions.StringLiteralValue
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotEquals
import kotlin.test.assertTrue
class TestNumericLiteralValue: FunSpec({
@ -22,66 +20,66 @@ class TestNumericLiteralValue: FunSpec({
test("testIdentity") {
val v = NumericLiteralValue(DataType.UWORD, 12345, dummyPos)
assertEquals(v, v)
assertFalse(v != v)
assertTrue(v <= v)
assertTrue(v >= v)
assertFalse(v < v)
assertFalse(v > v)
(v==v) shouldBe true
(v != v) shouldBe false
(v <= v) shouldBe true
(v >= v) shouldBe true
(v < v ) shouldBe false
(v > v ) shouldBe false
assertTrue(sameValueAndType(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.UWORD, 12345, dummyPos)))
sameValueAndType(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.UWORD, 12345, dummyPos)) shouldBe true
}
test("testEqualsAndNotEquals") {
assertEquals(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UBYTE, 100, dummyPos))
assertEquals(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UWORD, 100, dummyPos))
assertEquals(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos))
assertEquals(NumericLiteralValue(DataType.UWORD, 254, dummyPos), NumericLiteralValue(DataType.UBYTE, 254, dummyPos))
assertEquals(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.UWORD, 12345, dummyPos))
assertEquals(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.FLOAT, 12345.0, dummyPos))
assertEquals(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos), NumericLiteralValue(DataType.UBYTE, 100, dummyPos))
assertEquals(NumericLiteralValue(DataType.FLOAT, 22239.0, dummyPos), NumericLiteralValue(DataType.UWORD, 22239, dummyPos))
assertEquals(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos))
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) == NumericLiteralValue(DataType.UBYTE, 100, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) == NumericLiteralValue(DataType.UWORD, 100, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) == NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UWORD, 254, dummyPos) == NumericLiteralValue(DataType.UBYTE, 254, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UWORD, 12345, dummyPos) == NumericLiteralValue(DataType.UWORD, 12345, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UWORD, 12345, dummyPos) == NumericLiteralValue(DataType.FLOAT, 12345.0, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) == NumericLiteralValue(DataType.UBYTE, 100, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.FLOAT, 22239.0, dummyPos) == NumericLiteralValue(DataType.UWORD, 22239, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos) == NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos)) shouldBe true
assertTrue(sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UBYTE, 100, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UWORD, 100, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.UWORD, 254, dummyPos), NumericLiteralValue(DataType.UBYTE, 254, dummyPos)))
assertTrue(sameValueAndType(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.UWORD, 12345, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.FLOAT, 12345.0, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos), NumericLiteralValue(DataType.UBYTE, 100, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.FLOAT, 22239.0, dummyPos), NumericLiteralValue(DataType.UWORD, 22239, dummyPos)))
assertTrue(sameValueAndType(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos)))
sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UBYTE, 100, dummyPos)) shouldBe true
sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UWORD, 100, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.UWORD, 254, dummyPos), NumericLiteralValue(DataType.UBYTE, 254, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.UWORD, 12345, dummyPos)) shouldBe true
sameValueAndType(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.FLOAT, 12345.0, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos), NumericLiteralValue(DataType.UBYTE, 100, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.FLOAT, 22239.0, dummyPos), NumericLiteralValue(DataType.UWORD, 22239, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos)) shouldBe true
assertNotEquals(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UBYTE, 101, dummyPos))
assertNotEquals(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UWORD, 101, dummyPos))
assertNotEquals(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.FLOAT, 101.0, dummyPos))
assertNotEquals(NumericLiteralValue(DataType.UWORD, 245, dummyPos), NumericLiteralValue(DataType.UBYTE, 246, dummyPos))
assertNotEquals(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.UWORD, 12346, dummyPos))
assertNotEquals(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.FLOAT, 12346.0, dummyPos))
assertNotEquals(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.UBYTE, 9, dummyPos))
assertNotEquals(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.UWORD, 9, dummyPos))
assertNotEquals(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.FLOAT, 9.0, dummyPos))
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) != NumericLiteralValue(DataType.UBYTE, 101, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) != NumericLiteralValue(DataType.UWORD, 101, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) != NumericLiteralValue(DataType.FLOAT, 101.0, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UWORD, 245, dummyPos) != NumericLiteralValue(DataType.UBYTE, 246, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UWORD, 12345, dummyPos) != NumericLiteralValue(DataType.UWORD, 12346, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UWORD, 12345, dummyPos) != NumericLiteralValue(DataType.FLOAT, 12346.0, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos) != NumericLiteralValue(DataType.UBYTE, 9, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos) != NumericLiteralValue(DataType.UWORD, 9, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos) != NumericLiteralValue(DataType.FLOAT, 9.0, dummyPos)) shouldBe true
assertFalse(sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UBYTE, 101, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UWORD, 101, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.FLOAT, 101.0, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.UWORD, 245, dummyPos), NumericLiteralValue(DataType.UBYTE, 246, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.UWORD, 12346, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.FLOAT, 12346.0, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.UBYTE, 9, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.UWORD, 9, dummyPos)))
assertFalse(sameValueAndType(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.FLOAT, 9.0, dummyPos)))
sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UBYTE, 101, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.UWORD, 101, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.UBYTE, 100, dummyPos), NumericLiteralValue(DataType.FLOAT, 101.0, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.UWORD, 245, dummyPos), NumericLiteralValue(DataType.UBYTE, 246, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.UWORD, 12346, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.UWORD, 12345, dummyPos), NumericLiteralValue(DataType.FLOAT, 12346.0, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.UBYTE, 9, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.UWORD, 9, dummyPos)) shouldBe false
sameValueAndType(NumericLiteralValue(DataType.FLOAT, 9.99, dummyPos), NumericLiteralValue(DataType.FLOAT, 9.0, dummyPos)) shouldBe false
}
test("testEqualsRef") {
assertEquals(StringLiteralValue("hello", false, dummyPos), StringLiteralValue("hello", false, dummyPos))
assertNotEquals(StringLiteralValue("hello", false, dummyPos), StringLiteralValue("bye", false, dummyPos))
assertEquals(StringLiteralValue("hello", true, dummyPos), StringLiteralValue("hello", true, dummyPos))
assertNotEquals(StringLiteralValue("hello", true, dummyPos), StringLiteralValue("bye", true, dummyPos))
assertNotEquals(StringLiteralValue("hello", true, dummyPos), StringLiteralValue("hello", false, dummyPos))
(StringLiteralValue("hello", false, dummyPos) == StringLiteralValue("hello", false, dummyPos)) shouldBe true
(StringLiteralValue("hello", false, dummyPos) != StringLiteralValue("bye", false, dummyPos)) shouldBe true
(StringLiteralValue("hello", true, dummyPos) == StringLiteralValue("hello", true, dummyPos)) shouldBe true
(StringLiteralValue("hello", true, dummyPos) != StringLiteralValue("bye", true, dummyPos)) shouldBe true
(StringLiteralValue("hello", true, dummyPos) != StringLiteralValue("hello", false, dummyPos)) shouldBe true
val lvOne = NumericLiteralValue(DataType.UBYTE, 1, dummyPos)
val lvTwo = NumericLiteralValue(DataType.UBYTE, 2, dummyPos)
@ -93,44 +91,44 @@ class TestNumericLiteralValue: FunSpec({
val lv1 = ArrayLiteralValue(InferredTypes.InferredType.known(DataType.ARRAY_UB), arrayOf(lvOne, lvTwo, lvThree), dummyPos)
val lv2 = ArrayLiteralValue(InferredTypes.InferredType.known(DataType.ARRAY_UB), arrayOf(lvOneR, lvTwoR, lvThreeR), dummyPos)
val lv3 = ArrayLiteralValue(InferredTypes.InferredType.known(DataType.ARRAY_UB), arrayOf(lvOneR, lvTwoR, lvFour), dummyPos)
assertEquals(lv1, lv2)
assertNotEquals(lv1, lv3)
lv1 shouldBe lv2
lv1 shouldNotBe lv3
}
test("testGreaterThan") {
assertTrue(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) > NumericLiteralValue(DataType.UBYTE, 99, dummyPos))
assertTrue(NumericLiteralValue(DataType.UWORD, 254, dummyPos) > NumericLiteralValue(DataType.UWORD, 253, dummyPos))
assertTrue(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) > NumericLiteralValue(DataType.FLOAT, 99.9, dummyPos))
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) > NumericLiteralValue(DataType.UBYTE, 99, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UWORD, 254, dummyPos) > NumericLiteralValue(DataType.UWORD, 253, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) > NumericLiteralValue(DataType.FLOAT, 99.9, dummyPos)) shouldBe true
assertTrue(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) >= NumericLiteralValue(DataType.UBYTE, 100, dummyPos))
assertTrue(NumericLiteralValue(DataType.UWORD, 254, dummyPos) >= NumericLiteralValue(DataType.UWORD, 254, dummyPos))
assertTrue(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) >= NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos))
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) >= NumericLiteralValue(DataType.UBYTE, 100, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UWORD, 254, dummyPos) >= NumericLiteralValue(DataType.UWORD, 254, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) >= NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos)) shouldBe true
assertFalse(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) > NumericLiteralValue(DataType.UBYTE, 100, dummyPos))
assertFalse(NumericLiteralValue(DataType.UWORD, 254, dummyPos) > NumericLiteralValue(DataType.UWORD, 254, dummyPos))
assertFalse(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) > NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos))
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) > NumericLiteralValue(DataType.UBYTE, 100, dummyPos)) shouldBe false
(NumericLiteralValue(DataType.UWORD, 254, dummyPos) > NumericLiteralValue(DataType.UWORD, 254, dummyPos)) shouldBe false
(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) > NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos)) shouldBe false
assertFalse(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) >= NumericLiteralValue(DataType.UBYTE, 101, dummyPos))
assertFalse(NumericLiteralValue(DataType.UWORD, 254, dummyPos) >= NumericLiteralValue(DataType.UWORD, 255, dummyPos))
assertFalse(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) >= NumericLiteralValue(DataType.FLOAT, 100.1, dummyPos))
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) >= NumericLiteralValue(DataType.UBYTE, 101, dummyPos)) shouldBe false
(NumericLiteralValue(DataType.UWORD, 254, dummyPos) >= NumericLiteralValue(DataType.UWORD, 255, dummyPos)) shouldBe false
(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) >= NumericLiteralValue(DataType.FLOAT, 100.1, dummyPos)) shouldBe false
}
test("testLessThan") {
assertTrue(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) < NumericLiteralValue(DataType.UBYTE, 101, dummyPos))
assertTrue(NumericLiteralValue(DataType.UWORD, 254, dummyPos) < NumericLiteralValue(DataType.UWORD, 255, dummyPos))
assertTrue(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) < NumericLiteralValue(DataType.FLOAT, 100.1, dummyPos))
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) < NumericLiteralValue(DataType.UBYTE, 101, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UWORD, 254, dummyPos) < NumericLiteralValue(DataType.UWORD, 255, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) < NumericLiteralValue(DataType.FLOAT, 100.1, dummyPos)) shouldBe true
assertTrue(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) <= NumericLiteralValue(DataType.UBYTE, 100, dummyPos))
assertTrue(NumericLiteralValue(DataType.UWORD, 254, dummyPos) <= NumericLiteralValue(DataType.UWORD, 254, dummyPos))
assertTrue(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) <= NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos))
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) <= NumericLiteralValue(DataType.UBYTE, 100, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.UWORD, 254, dummyPos) <= NumericLiteralValue(DataType.UWORD, 254, dummyPos)) shouldBe true
(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) <= NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos)) shouldBe true
assertFalse(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) < NumericLiteralValue(DataType.UBYTE, 100, dummyPos))
assertFalse(NumericLiteralValue(DataType.UWORD, 254, dummyPos) < NumericLiteralValue(DataType.UWORD, 254, dummyPos))
assertFalse(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) < NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos))
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) < NumericLiteralValue(DataType.UBYTE, 100, dummyPos)) shouldBe false
(NumericLiteralValue(DataType.UWORD, 254, dummyPos) < NumericLiteralValue(DataType.UWORD, 254, dummyPos)) shouldBe false
(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) < NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos)) shouldBe false
assertFalse(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) <= NumericLiteralValue(DataType.UBYTE, 99, dummyPos))
assertFalse(NumericLiteralValue(DataType.UWORD, 254, dummyPos) <= NumericLiteralValue(DataType.UWORD, 253, dummyPos))
assertFalse(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) <= NumericLiteralValue(DataType.FLOAT, 99.9, dummyPos))
(NumericLiteralValue(DataType.UBYTE, 100, dummyPos) <= NumericLiteralValue(DataType.UBYTE, 99, dummyPos)) shouldBe false
(NumericLiteralValue(DataType.UWORD, 254, dummyPos) <= NumericLiteralValue(DataType.UWORD, 253, dummyPos)) shouldBe false
(NumericLiteralValue(DataType.FLOAT, 100.0, dummyPos) <= NumericLiteralValue(DataType.FLOAT, 99.9, dummyPos)) shouldBe false
}
})

View File

@ -1,6 +1,11 @@
package prog8tests
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.types.instanceOf
import io.kotest.matchers.types.shouldBeSameInstanceAs
import prog8.ast.Program
import prog8.ast.base.DataType
import prog8.ast.base.ParentSentinel
@ -14,7 +19,6 @@ import prog8tests.helpers.DummyMemsizer
import prog8tests.helpers.DummyStringEncoder
import prog8tests.helpers.assertSuccess
import prog8tests.helpers.compileText
import kotlin.test.*
class TestOptimization: FunSpec({
test("testRemoveEmptySubroutineExceptStart") {
@ -31,9 +35,13 @@ class TestOptimization: FunSpec({
val toplevelModule = result.program.toplevelModule
val mainBlock = toplevelModule.statements.single() as Block
val startSub = mainBlock.statements.single() as Subroutine
assertSame(result.program.entrypoint, startSub)
assertEquals("start", startSub.name, "only start sub should remain")
assertTrue(startSub.statements.single() is Return, "compiler has inserted return in empty subroutines")
result.program.entrypoint shouldBeSameInstanceAs startSub
withClue("only start sub should remain") {
startSub.name shouldBe "start"
}
withClue("compiler has inserted return in empty subroutines") {
startSub.statements.single() shouldBe instanceOf<Return>()
}
}
test("testDontRemoveEmptySubroutineIfItsReferenced") {
@ -53,10 +61,12 @@ class TestOptimization: FunSpec({
val mainBlock = toplevelModule.statements.single() as Block
val startSub = mainBlock.statements[0] as Subroutine
val emptySub = mainBlock.statements[1] as Subroutine
assertSame(result.program.entrypoint, startSub)
assertEquals("start", startSub.name)
assertEquals("empty", emptySub.name)
assertTrue(emptySub.statements.single() is Return, "compiler has inserted return in empty subroutines")
result.program.entrypoint shouldBeSameInstanceAs startSub
startSub.name shouldBe "start"
emptySub.name shouldBe "empty"
withClue("compiler has inserted return in empty subroutines") {
emptySub.statements.single() shouldBe instanceOf<Return>()
}
}
test("testGeneratedConstvalueInheritsProperParentLinkage") {
@ -64,14 +74,14 @@ class TestOptimization: FunSpec({
val tc = TypecastExpression(number, DataType.BYTE, false, Position.DUMMY)
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
tc.linkParents(ParentSentinel)
assertNotNull(tc.parent)
assertNotNull(number.parent)
assertSame(tc, number.parent)
tc.parent shouldNotBe null
number.parent shouldNotBe null
tc shouldBeSameInstanceAs number.parent
val constvalue = tc.constValue(program)!!
assertIs<NumericLiteralValue>(constvalue)
assertEquals(11, constvalue.number.toInt())
assertEquals(DataType.BYTE, constvalue.type)
assertSame(tc, constvalue.parent)
constvalue shouldBe instanceOf<NumericLiteralValue>()
constvalue.number.toInt() shouldBe 11
constvalue.type shouldBe DataType.BYTE
tc shouldBeSameInstanceAs constvalue.parent
}
test("testConstantFoldedAndSilentlyTypecastedForInitializerValues") {
@ -88,7 +98,7 @@ class TestOptimization: FunSpec({
"""
val result = compileText(C64Target, true, sourcecode).assertSuccess()
val mainsub = result.program.entrypoint
assertEquals(10, mainsub.statements.size)
mainsub.statements.size shouldBe 10
val declTest = mainsub.statements[0] as VarDecl
val declX1 = mainsub.statements[1] as VarDecl
val initX1 = mainsub.statements[2] as Assignment
@ -98,19 +108,19 @@ class TestOptimization: FunSpec({
val initY1 = mainsub.statements[6] as Assignment
val declY2 = mainsub.statements[7] as VarDecl
val initY2 = mainsub.statements[8] as Assignment
assertIs<Return>(mainsub.statements[9])
assertEquals(10.0, (declTest.value as NumericLiteralValue).number.toDouble())
assertNull(declX1.value)
assertNull(declX2.value)
assertNull(declY1.value)
assertNull(declY2.value)
assertEquals(DataType.BYTE, (initX1.value as NumericLiteralValue).type)
assertEquals(11.0, (initX1.value as NumericLiteralValue).number.toDouble())
assertEquals(DataType.BYTE, (initX2.value as NumericLiteralValue).type)
assertEquals(11.0, (initX2.value as NumericLiteralValue).number.toDouble())
assertEquals(DataType.UBYTE, (initY1.value as NumericLiteralValue).type)
assertEquals(11.0, (initY1.value as NumericLiteralValue).number.toDouble())
assertEquals(DataType.UBYTE, (initY2.value as NumericLiteralValue).type)
assertEquals(11.0, (initY2.value as NumericLiteralValue).number.toDouble())
mainsub.statements[9] shouldBe instanceOf<Return>()
(declTest.value as NumericLiteralValue).number.toDouble() shouldBe 10.0
declX1.value shouldBe null
declX2.value shouldBe null
declY1.value shouldBe null
declY2.value shouldBe null
(initX1.value as NumericLiteralValue).type shouldBe DataType.BYTE
(initX1.value as NumericLiteralValue).number.toDouble() shouldBe 11.0
(initX2.value as NumericLiteralValue).type shouldBe DataType.BYTE
(initX2.value as NumericLiteralValue).number.toDouble() shouldBe 11.0
(initY1.value as NumericLiteralValue).type shouldBe DataType.UBYTE
(initY1.value as NumericLiteralValue).number.toDouble() shouldBe 11.0
(initY2.value as NumericLiteralValue).type shouldBe DataType.UBYTE
(initY2.value as NumericLiteralValue).number.toDouble() shouldBe 11.0
}
})

View File

@ -3,67 +3,73 @@ package prog8tests
import com.github.michaelbull.result.Ok
import com.github.michaelbull.result.expectError
import com.github.michaelbull.result.getOrElse
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
import io.kotest.matchers.shouldBe
import prog8.compiler.target.cbm.Petscii
import java.io.CharConversionException
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class TestPetscii: FunSpec({
test("testZero") {
assertThat(Petscii.encodePetscii("\u0000", true), equalTo(Ok(listOf<Short>(0))))
assertThat(Petscii.encodePetscii("\u0000", false), equalTo(Ok(listOf<Short>(0))))
assertThat(Petscii.decodePetscii(listOf(0), true), equalTo("\u0000"))
assertThat(Petscii.decodePetscii(listOf(0), false), equalTo("\u0000"))
Petscii.encodePetscii("\u0000", true) shouldBe Ok(listOf<Short>(0))
Petscii.encodePetscii("\u0000", false) shouldBe Ok(listOf<Short>(0))
Petscii.decodePetscii(listOf(0), true) shouldBe "\u0000"
Petscii.decodePetscii(listOf(0), false) shouldBe "\u0000"
}
test("testLowercase") {
assertThat(Petscii.encodePetscii("hello WORLD 123 @!£", true), equalTo(
Ok(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(Ok(listOf<Short>(0x12)))) // reverse vid
assertThat(Petscii.encodePetscii("", true), equalTo(Ok(listOf<Short>(0xfa))))
assertThat("expect lowercase error fallback", Petscii.encodePetscii("π", true), equalTo(Ok(listOf<Short>(255))))
assertThat("expect lowercase error fallback", Petscii.encodePetscii("", true), equalTo(Ok(listOf<Short>(0xd3))))
Petscii.encodePetscii("hello WORLD 123 @!£", true) shouldBe
Ok(listOf<Short>(72, 69, 76, 76, 79, 32, 0xd7, 0xcf, 0xd2, 0xcc, 0xc4, 32, 49, 50, 51, 32, 64, 33, 0x5c))
Petscii.encodePetscii("\uf11a", true) shouldBe Ok(listOf<Short>(0x12)) // reverse vid
Petscii.encodePetscii("", true) shouldBe Ok(listOf<Short>(0xfa))
withClue("expect lowercase error fallback") {
Petscii.encodePetscii("π", true) shouldBe Ok(listOf<Short>(255))
Petscii.encodePetscii("", true) shouldBe Ok(listOf<Short>(0xd3))
}
assertThat(Petscii.decodePetscii(listOf(72, 0xd7, 0x5c, 0xfa, 0x12), true), equalTo("hW£✓\uF11A"))
Petscii.decodePetscii(listOf(72, 0xd7, 0x5c, 0xfa, 0x12), true) shouldBe "hW£✓\uF11A"
}
test("testUppercase") {
assertThat(Petscii.encodePetscii("HELLO 123 @!£"), equalTo(
Ok(listOf<Short>(72, 69, 76, 76, 79, 32, 49, 50, 51, 32, 64, 33, 0x5c))))
assertThat(Petscii.encodePetscii("\uf11a"), equalTo(Ok(listOf<Short>(0x12)))) // reverse vid
assertThat(Petscii.encodePetscii(""), equalTo(Ok(listOf<Short>(0xd3))))
assertThat(Petscii.encodePetscii("π"), equalTo(Ok(listOf<Short>(0xff))))
assertThat("expecting fallback", Petscii.encodePetscii(""), equalTo(Ok(listOf<Short>(250))))
Petscii.encodePetscii("HELLO 123 @!£") shouldBe
Ok(listOf<Short>(72, 69, 76, 76, 79, 32, 49, 50, 51, 32, 64, 33, 0x5c))
Petscii.encodePetscii("\uf11a") shouldBe Ok(listOf<Short>(0x12)) // reverse vid
Petscii.encodePetscii("") shouldBe Ok(listOf<Short>(0xd3))
Petscii.encodePetscii("π") shouldBe Ok(listOf<Short>(0xff))
withClue("expecting fallback") {
Petscii.encodePetscii("") shouldBe Ok(listOf<Short>(250))
}
assertThat(Petscii.decodePetscii(listOf(72, 0x5c, 0xd3, 0xff)), equalTo("H£♥π"))
Petscii.decodePetscii(listOf(72, 0x5c, 0xd3, 0xff)) shouldBe "H£♥π"
}
test("testScreencodeLowercase") {
assertThat(Petscii.encodeScreencode("hello WORLD 123 @!£", true), equalTo(
Petscii.encodeScreencode("hello WORLD 123 @!£", true) shouldBe
Ok(listOf<Short>(0x08, 0x05, 0x0c, 0x0c, 0x0f, 0x20, 0x57, 0x4f, 0x52, 0x4c, 0x44, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c))
))
assertThat(Petscii.encodeScreencode("", true), equalTo(Ok(listOf<Short>(0x7a))))
assertThat("expect fallback", Petscii.encodeScreencode("", true), equalTo(Ok(listOf<Short>(83))))
assertThat("expect fallback", Petscii.encodeScreencode("π", true), equalTo(Ok(listOf<Short>(94))))
Petscii.encodeScreencode("", true) shouldBe Ok(listOf<Short>(0x7a))
withClue("expect fallback") {
Petscii.encodeScreencode("", true) shouldBe Ok(listOf<Short>(83))
Petscii.encodeScreencode("π", true) shouldBe Ok(listOf<Short>(94))
}
assertThat(Petscii.decodeScreencode(listOf(0x08, 0x57, 0x1c, 0x7a), true), equalTo("hW£✓"))
Petscii.decodeScreencode(listOf(0x08, 0x57, 0x1c, 0x7a), true) shouldBe "hW£✓"
}
test("testScreencodeUppercase") {
assertThat(Petscii.encodeScreencode("WORLD 123 @!£"), equalTo(
Ok(listOf<Short>(0x17, 0x0f, 0x12, 0x0c, 0x04, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c))))
assertThat(Petscii.encodeScreencode(""), equalTo(Ok(listOf<Short>(0x53))))
assertThat(Petscii.encodeScreencode("π"), equalTo(Ok(listOf<Short>(0x5e))))
assertThat(Petscii.encodeScreencode("HELLO"), equalTo(Ok(listOf<Short>(8, 5, 12, 12, 15))))
assertThat("expecting fallback", Petscii.encodeScreencode("hello"), equalTo(Ok(listOf<Short>(8, 5, 12, 12, 15))))
assertThat("expecting fallback", Petscii.encodeScreencode(""), equalTo(Ok(listOf<Short>(122))))
Petscii.encodeScreencode("WORLD 123 @!£") shouldBe
Ok(listOf<Short>(0x17, 0x0f, 0x12, 0x0c, 0x04, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c))
Petscii.encodeScreencode("") shouldBe Ok(listOf<Short>(0x53))
Petscii.encodeScreencode("π") shouldBe Ok(listOf<Short>(0x5e))
Petscii.encodeScreencode("HELLO") shouldBe Ok(listOf<Short>(8, 5, 12, 12, 15))
withClue("expecting fallback") {
Petscii.encodeScreencode("hello") shouldBe Ok(listOf<Short>(8, 5, 12, 12, 15))
Petscii.encodeScreencode("") shouldBe Ok(listOf<Short>(122))
}
assertThat(Petscii.decodeScreencode(listOf(0x17, 0x1c, 0x53, 0x5e)), equalTo("W£♥π"))
Petscii.decodeScreencode(listOf(0x17, 0x1c, 0x53, 0x5e)) shouldBe "W£♥π"
}
test("testErrorCases") {
@ -72,14 +78,14 @@ class TestPetscii: FunSpec({
Petscii.encodeScreencode("~", true).expectError { "shouldn't be able to encode tilde" }
Petscii.encodeScreencode("~", false).expectError { "shouldn't be able to encode tilde" }
assertFailsWith<CharConversionException> { Petscii.decodePetscii(listOf<Short>(-1), true) }
assertFailsWith<CharConversionException> { Petscii.decodePetscii(listOf<Short>(256), true) }
assertFailsWith<CharConversionException> { Petscii.decodePetscii(listOf<Short>(-1), false) }
assertFailsWith<CharConversionException> { Petscii.decodePetscii(listOf<Short>(256), false) }
assertFailsWith<CharConversionException> { Petscii.decodeScreencode(listOf<Short>(-1), true) }
assertFailsWith<CharConversionException> { Petscii.decodeScreencode(listOf<Short>(256), true) }
assertFailsWith<CharConversionException> { Petscii.decodeScreencode(listOf<Short>(-1), false) }
assertFailsWith<CharConversionException> { Petscii.decodeScreencode(listOf<Short>(256), false) }
shouldThrow<CharConversionException> { Petscii.decodePetscii(listOf<Short>(-1), true) }
shouldThrow<CharConversionException> { Petscii.decodePetscii(listOf<Short>(256), true) }
shouldThrow<CharConversionException> { Petscii.decodePetscii(listOf<Short>(-1), false) }
shouldThrow<CharConversionException> { Petscii.decodePetscii(listOf<Short>(256), false) }
shouldThrow<CharConversionException> { Petscii.decodeScreencode(listOf<Short>(-1), true) }
shouldThrow<CharConversionException> { Petscii.decodeScreencode(listOf<Short>(256), true) }
shouldThrow<CharConversionException> { Petscii.decodeScreencode(listOf<Short>(-1), false) }
shouldThrow<CharConversionException> { Petscii.decodeScreencode(listOf<Short>(256), false) }
Petscii.scr2petscii(-1).expectError { "-1 should error" }
Petscii.scr2petscii(256).expectError { "256 should error" }
@ -98,30 +104,30 @@ class TestPetscii: FunSpec({
Petscii.encodePetscii("~", false).expectError { "shouldn't have translation for tilde" }
Petscii.encodePetscii("~", true).expectError { "shouldn't have translation for tilde" }
assertEquals(94, encodeP('^', false))
assertEquals(94, encodeP('^', true))
assertEquals(30, encodeS('^', false))
assertEquals(30, encodeS('^', true))
assertEquals(228, encodeP('_', false))
assertEquals(228, encodeP('_', true))
assertEquals(100, encodeS('_', false))
assertEquals(100, encodeS('_', true))
assertEquals(243, encodeP('{', false))
assertEquals(243, encodeP('{', true))
assertEquals(115, encodeS('{', false))
assertEquals(115, encodeS('{', true))
assertEquals(235, encodeP('}', false))
assertEquals(235, encodeP('}', true))
assertEquals(107, encodeS('}', false))
assertEquals(107, encodeS('}', true))
assertEquals(221, encodeP('|', false))
assertEquals(221, encodeP('|', true))
assertEquals(93, encodeS('|', false))
assertEquals(93, encodeS('|', true))
assertEquals(205, encodeP('\\', false))
assertEquals(205, encodeP('\\', true))
assertEquals(77, encodeS('\\', false))
assertEquals(77, encodeS('\\', true))
encodeP('^', false) shouldBe 94
encodeP('^', true) shouldBe 94
encodeS('^', false) shouldBe 30
encodeS('^', true) shouldBe 30
encodeP('_', false) shouldBe 228
encodeP('_', true) shouldBe 228
encodeS('_', false) shouldBe 100
encodeS('_', true) shouldBe 100
encodeP('{', false) shouldBe 243
encodeP('{', true) shouldBe 243
encodeS('{', false) shouldBe 115
encodeS('{', true) shouldBe 115
encodeP('}', false) shouldBe 235
encodeP('}', true) shouldBe 235
encodeS('}', false) shouldBe 107
encodeS('}', true) shouldBe 107
encodeP('|', false) shouldBe 221
encodeP('|', true) shouldBe 221
encodeS('|', false) shouldBe 93
encodeS('|', true) shouldBe 93
encodeP('\\', false) shouldBe 205
encodeP('\\', true) shouldBe 205
encodeS('\\', false) shouldBe 77
encodeS('\\', true) shouldBe 77
}
test("testBoxDrawingCharsEncoding") {
@ -129,59 +135,59 @@ class TestPetscii: FunSpec({
fun encodeS(c: Char, lower: Boolean) = Petscii.encodeScreencode(c.toString(), lower).getOrElse { throw it }.single()
// pipe char
assertEquals(221, encodeP('|', false))
assertEquals(221, encodeP('|', true))
assertEquals(93, encodeS('|', false))
assertEquals(93, encodeS('|', true))
encodeP('|', false) shouldBe 221
encodeP('|', true) shouldBe 221
encodeS('|', false) shouldBe 93
encodeS('|', true) shouldBe 93
// ... same as '│', 0x7D -> BOX DRAWINGS LIGHT VERTICAL
assertEquals(221, encodeP('│', false))
assertEquals(221, encodeP('│', true))
assertEquals(93, encodeS('│', false))
assertEquals(93, encodeS('│', true))
encodeP('│', false) shouldBe 221
encodeP('│', true) shouldBe 221
encodeS('│', false) shouldBe 93
encodeS('│', true) shouldBe 93
// underscore
assertEquals(228, encodeP('_', false))
assertEquals(228, encodeP('_', true))
assertEquals(100, encodeS('_', false))
assertEquals(100, encodeS('_', true))
encodeP('_', false) shouldBe 228
encodeP('_', true) shouldBe 228
encodeS('_', false) shouldBe 100
encodeS('_', true) shouldBe 100
// ... same as '▁', 0xE4 LOWER ONE EIGHTH BLOCK
assertEquals(228, encodeP('▁', false))
assertEquals(228, encodeP('▁', true))
assertEquals(100, encodeS('▁', false))
assertEquals(100, encodeS('▁', true))
encodeP('▁', false) shouldBe 228
encodeP('▁', true) shouldBe 228
encodeS('▁', false) shouldBe 100
encodeS('▁', true) shouldBe 100
// ─ 0xC0 -> BOX DRAWINGS LIGHT HORIZONTAL
assertEquals(192, encodeP('─', false))
assertEquals(192, encodeP('─', true))
assertEquals(64, encodeS('─', false))
assertEquals(64, encodeS('─', true))
encodeP('─', false) shouldBe 192
encodeP('─', true) shouldBe 192
encodeS('─', false) shouldBe 64
encodeS('─', true) shouldBe 64
// │ 0x62 -> BOX DRAWINGS LIGHT VERTICAL
assertEquals(221, encodeP('│', false))
assertEquals(221, encodeP('│', true))
assertEquals(93, encodeS('│', false))
assertEquals(93, encodeS('│', true))
encodeP('│', false) shouldBe 221
encodeP('│', true) shouldBe 221
encodeS('│', false) shouldBe 93
encodeS('│', true) shouldBe 93
}
test("testBoxDrawingCharsDecoding") {
// ─ 0xC0 -> BOX DRAWINGS LIGHT HORIZONTAL
assertEquals('\uf13b', Petscii.decodePetscii(listOf(195), false).single(), "BOX DRAWINGS LIGHT HORIZONTAL ONE EIGHTH UP (CUS)")
assertEquals('C', Petscii.decodePetscii(listOf(195), true).single())
assertEquals('─', Petscii.decodePetscii(listOf(192), false).single())
assertEquals('─', Petscii.decodePetscii(listOf(192), true).single())
assertEquals('\uf13b', Petscii.decodeScreencode(listOf(67), false).single(), "BOX DRAWINGS LIGHT HORIZONTAL ONE EIGHTH UP (CUS)")
assertEquals('C', Petscii.decodeScreencode(listOf(67), true).single())
assertEquals('─', Petscii.decodeScreencode(listOf(64), false).single())
assertEquals('─', Petscii.decodeScreencode(listOf(64), true).single())
Petscii.decodePetscii(listOf(195), false).single() shouldBe '\uf13b' //"BOX DRAWINGS LIGHT HORIZONTAL ONE EIGHTH UP (CUS)"
Petscii.decodePetscii(listOf(195), true).single() shouldBe 'C'
Petscii.decodePetscii(listOf(192), false).single() shouldBe '─'
Petscii.decodePetscii(listOf(192), true).single() shouldBe '─'
Petscii.decodeScreencode(listOf(67), false).single() shouldBe '\uf13b' //"BOX DRAWINGS LIGHT HORIZONTAL ONE EIGHTH UP (CUS)"
Petscii.decodeScreencode(listOf(67), true).single() shouldBe 'C'
Petscii.decodeScreencode(listOf(64), false).single() shouldBe '─'
Petscii.decodeScreencode(listOf(64), true).single() shouldBe '─'
// │ 0x62 -> BOX DRAWINGS LIGHT VERTICAL
assertEquals('│', Petscii.decodePetscii(listOf(125), false).single())
assertEquals('│', Petscii.decodePetscii(listOf(125), true).single())
assertEquals('│', Petscii.decodePetscii(listOf(221), false).single())
assertEquals('│', Petscii.decodePetscii(listOf(221), true).single())
assertEquals('│', Petscii.decodeScreencode(listOf(93), false).single())
assertEquals('│', Petscii.decodeScreencode(listOf(93), true).single())
assertEquals('\uf13c', Petscii.decodeScreencode(listOf(66), false).single(), "BOX DRAWINGS LIGHT VERTICAL ONE EIGHTH LEFT (CUS)")
assertEquals('B', Petscii.decodeScreencode(listOf(66), true).single())
Petscii.decodePetscii(listOf(125), false).single() shouldBe '│'
Petscii.decodePetscii(listOf(125), true).single() shouldBe '│'
Petscii.decodePetscii(listOf(221), false).single() shouldBe '│'
Petscii.decodePetscii(listOf(221), true).single() shouldBe '│'
Petscii.decodeScreencode(listOf(93), false).single() shouldBe '│'
Petscii.decodeScreencode(listOf(93), true).single() shouldBe '│'
Petscii.decodeScreencode(listOf(66), false).single() shouldBe '\uf13c' // "BOX DRAWINGS LIGHT VERTICAL ONE EIGHTH LEFT (CUS)"
Petscii.decodeScreencode(listOf(66), true).single() shouldBe 'B'
}
})

View File

@ -1,6 +1,10 @@
package prog8tests
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.instanceOf
import io.kotest.matchers.types.shouldBeSameInstanceAs
import prog8.ast.GlobalNamespace
import prog8.ast.base.ParentSentinel
import prog8.ast.expressions.NumericLiteralValue
@ -8,7 +12,6 @@ import prog8.ast.statements.*
import prog8.compiler.target.C64Target
import prog8tests.helpers.assertSuccess
import prog8tests.helpers.compileText
import kotlin.test.*
class TestScoping: FunSpec({
@ -23,9 +26,9 @@ class TestScoping: FunSpec({
val result = compileText(C64Target, false, src, writeAssembly = false).assertSuccess()
val module = result.program.toplevelModule
assertIs<GlobalNamespace>(module.parent)
assertSame(result.program, module.program)
assertIs<ParentSentinel>(module.parent.parent)
module.parent shouldBe instanceOf<GlobalNamespace>()
module.program shouldBeSameInstanceAs result.program
module.parent.parent shouldBe instanceOf<ParentSentinel>()
}
test("testAnonScopeVarsMovedIntoSubroutineScope") {
@ -45,15 +48,25 @@ class TestScoping: FunSpec({
val mainBlock = module.statements.single() as Block
val start = mainBlock.statements.single() as Subroutine
val repeatbody = start.statements.filterIsInstance<RepeatLoop>().single().body
assertFalse(mainBlock.statements.any { it is VarDecl }, "no vars moved to main block")
withClue("no vars moved to main block") {
mainBlock.statements.any { it is VarDecl } shouldBe false
}
val subroutineVars = start.statements.filterIsInstance<VarDecl>()
assertEquals(1, subroutineVars.size, "var from repeat anonscope must be moved up to subroutine")
assertEquals("xx", subroutineVars[0].name)
assertFalse(repeatbody.statements.any { it is VarDecl }, "var should have been removed from repeat anonscope")
withClue("var from repeat anonscope must be moved up to subroutine") {
subroutineVars.size shouldBe 1
}
subroutineVars[0].name shouldBe "xx"
withClue("var should have been removed from repeat anonscope") {
repeatbody.statements.any { it is VarDecl } shouldBe false
}
val initassign = repeatbody.statements[0] as? Assignment
assertEquals(listOf("xx"), initassign?.target?.identifier?.nameInSource, "vardecl in repeat should be replaced by init assignment")
assertEquals(99, (initassign?.value as? NumericLiteralValue)?.number?.toInt(), "vardecl in repeat should be replaced by init assignment")
assertTrue(repeatbody.statements[1] is PostIncrDecr)
withClue("vardecl in repeat should be replaced by init assignment") {
initassign?.target?.identifier?.nameInSource shouldBe listOf("xx")
}
withClue("vardecl in repeat should be replaced by init assignment") {
(initassign?.value as? NumericLiteralValue)?.number?.toInt() shouldBe 99
}
repeatbody.statements[1] shouldBe instanceOf<PostIncrDecr>()
}
test("testLabelsWithAnonScopes") {
@ -115,7 +128,9 @@ class TestScoping: FunSpec({
val mainBlock = module.statements.single() as Block
val start = mainBlock.statements.single() as Subroutine
val labels = start.statements.filterIsInstance<Label>()
assertEquals(1, labels.size, "only one label in subroutine scope")
withClue("only one label in subroutine scope") {
labels.size shouldBe 1
}
}
})

View File

@ -1,6 +1,11 @@
package prog8tests
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.types.instanceOf
import prog8.ast.base.DataType
import prog8.ast.expressions.*
import prog8.ast.statements.*
@ -9,7 +14,6 @@ import prog8tests.helpers.ErrorReporterForTests
import prog8tests.helpers.assertFailure
import prog8tests.helpers.assertSuccess
import prog8tests.helpers.compileText
import kotlin.test.*
class TestSubroutines: FunSpec({
@ -42,23 +46,27 @@ class TestSubroutines: FunSpec({
val mainBlock = module.statements.single() as Block
val asmfunc = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="asmfunc"}
val func = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="func"}
assertTrue(asmfunc.isAsmSubroutine)
assertEquals(DataType.STR, asmfunc.parameters.single().type)
assertTrue(asmfunc.statements.isEmpty())
assertFalse(func.isAsmSubroutine)
assertEquals(DataType.STR, func.parameters.single().type)
assertEquals(4, func.statements.size)
asmfunc.isAsmSubroutine shouldBe true
asmfunc.parameters.single().type shouldBe DataType.STR
asmfunc.statements.isEmpty() shouldBe true
func.isAsmSubroutine shouldBe false
func.parameters.single().type shouldBe DataType.STR
func.statements.size shouldBe 4
val paramvar = func.statements[0] as VarDecl
assertEquals("thing", paramvar.name)
assertEquals(DataType.STR, paramvar.datatype)
paramvar.name shouldBe "thing"
paramvar.datatype shouldBe DataType.STR
val assign = func.statements[2] as Assignment
assertEquals(listOf("t2"), assign.target.identifier!!.nameInSource)
assertTrue(assign.value is TypecastExpression, "str param in function body should not be transformed by normal compiler steps")
assertEquals(DataType.UWORD, (assign.value as TypecastExpression).type)
assign.target.identifier!!.nameInSource shouldBe listOf("t2")
withClue("str param in function body should not be transformed by normal compiler steps") {
assign.value shouldBe instanceOf<TypecastExpression>()
}
(assign.value as TypecastExpression).type shouldBe DataType.UWORD
val call = func.statements[3] as FunctionCallStatement
assertEquals("asmfunc", call.target.nameInSource.single())
assertTrue(call.args.single() is IdentifierReference, "str param in function body should not be transformed by normal compiler steps")
assertEquals("thing", (call.args.single() as IdentifierReference).nameInSource.single())
call.target.nameInSource.single() shouldBe "asmfunc"
withClue("str param in function body should not be transformed by normal compiler steps") {
call.args.single() shouldBe instanceOf<IdentifierReference>()
}
(call.args.single() as IdentifierReference).nameInSource.single() shouldBe "thing"
}
test("stringParameterAsmGen") {
@ -89,26 +97,34 @@ class TestSubroutines: FunSpec({
val mainBlock = module.statements.single() as Block
val asmfunc = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="asmfunc"}
val func = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="func"}
assertTrue(asmfunc.isAsmSubroutine)
assertEquals(DataType.STR, asmfunc.parameters.single().type)
assertTrue(asmfunc.statements.single() is Return)
assertFalse(func.isAsmSubroutine)
assertEquals(DataType.UWORD, func.parameters.single().type, "asmgen should have changed str to uword type")
assertTrue(asmfunc.statements.last() is Return)
asmfunc.isAsmSubroutine shouldBe true
asmfunc.parameters.single().type shouldBe DataType.STR
asmfunc.statements.single() shouldBe instanceOf<Return>()
func.isAsmSubroutine shouldBe false
withClue("asmgen should have changed str to uword type") {
func.parameters.single().type shouldBe DataType.UWORD
}
asmfunc.statements.last() shouldBe instanceOf<Return>()
assertEquals(5, func.statements.size)
assertTrue(func.statements[4] is Return)
func.statements.size shouldBe 5
func.statements[4] shouldBe instanceOf<Return>()
val paramvar = func.statements[0] as VarDecl
assertEquals("thing", paramvar.name)
assertEquals(DataType.UWORD, paramvar.datatype, "pre-asmgen should have changed str to uword type")
paramvar.name shouldBe "thing"
withClue("pre-asmgen should have changed str to uword type") {
paramvar.datatype shouldBe DataType.UWORD
}
val assign = func.statements[2] as Assignment
assertEquals(listOf("t2"), assign.target.identifier!!.nameInSource)
assertTrue(assign.value is IdentifierReference, "str param in function body should be treated as plain uword before asmgen")
assertEquals("thing", (assign.value as IdentifierReference).nameInSource.single())
assign.target.identifier!!.nameInSource shouldBe listOf("t2")
withClue("str param in function body should be treated as plain uword before asmgen") {
assign.value shouldBe instanceOf<IdentifierReference>()
}
(assign.value as IdentifierReference).nameInSource.single() shouldBe "thing"
val call = func.statements[3] as FunctionCallStatement
assertEquals("asmfunc", call.target.nameInSource.single())
assertTrue(call.args.single() is IdentifierReference, "str param in function body should be treated as plain uword and not been transformed")
assertEquals("thing", (call.args.single() as IdentifierReference).nameInSource.single())
call.target.nameInSource.single() shouldBe "asmfunc"
withClue("str param in function body should be treated as plain uword and not been transformed") {
call.args.single() shouldBe instanceOf<IdentifierReference>()
}
(call.args.single() as IdentifierReference).nameInSource.single() shouldBe "thing"
}
test("arrayParameterNotYetAllowed_ButShouldPerhapsBe") {
@ -129,8 +145,8 @@ class TestSubroutines: FunSpec({
val errors = ErrorReporterForTests()
compileText(C64Target, false, text, errors, false).assertFailure("currently array dt in signature is invalid") // TODO should not be invalid?
assertEquals(0, errors.warnings.size)
assertContains(errors.errors.single(), ".p8:9:16: Non-string pass-by-reference types cannot occur as a parameter type directly")
errors.warnings.size shouldBe 0
errors.errors.single() shouldContain ".p8:9:16: Non-string pass-by-reference types cannot occur as a parameter type directly"
}
// TODO allow this?
@ -163,12 +179,12 @@ class TestSubroutines: FunSpec({
val mainBlock = module.statements.single() as Block
val asmfunc = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="asmfunc"}
val func = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="func"}
assertTrue(asmfunc.isAsmSubroutine)
assertEquals(DataType.ARRAY_UB, asmfunc.parameters.single().type)
assertTrue(asmfunc.statements.isEmpty())
assertFalse(func.isAsmSubroutine)
assertEquals(DataType.ARRAY_UB, func.parameters.single().type)
assertTrue(func.statements.isEmpty())
asmfunc.isAsmSubroutine shouldBe true
asmfunc.parameters.single().type shouldBe DataType.ARRAY_UB
asmfunc.statements.isEmpty() shouldBe true
func.isAsmSubroutine shouldBe false
func.parameters.single().type shouldBe DataType.ARRAY_UB
func.statements.isEmpty() shouldBe true
}
test("testUwordParameterAndNormalVarIndexedAsArrayWorkAsDirectMemoryRead") {
@ -193,25 +209,27 @@ class TestSubroutines: FunSpec({
val module = result.program.toplevelModule
val block = module.statements.single() as Block
val thing = block.statements.filterIsInstance<Subroutine>().single {it.name=="thing"}
assertEquals("main", block.name)
assertEquals(10, thing.statements.size, "rr, xx, xx assign, yy, yy assign, other, other assign 0, zz, zz assign, return")
block.name shouldBe "main"
thing.statements.size shouldBe 10 // rr, xx, xx assign, yy, yy assign, other, other assign 0, zz, zz assign, return
val xx = thing.statements[1] as VarDecl
assertNull(xx.value, "vardecl init values must have been moved to separate assignments")
withClue("vardecl init values must have been moved to separate assignments") {
xx.value shouldBe null
}
val assignXX = thing.statements[2] as Assignment
val assignYY = thing.statements[4] as Assignment
val assignZZ = thing.statements[8] as Assignment
assertEquals(listOf("xx"), assignXX.target.identifier!!.nameInSource)
assertEquals(listOf("yy"), assignYY.target.identifier!!.nameInSource)
assertEquals(listOf("zz"), assignZZ.target.identifier!!.nameInSource)
assignXX.target.identifier!!.nameInSource shouldBe listOf("xx")
assignYY.target.identifier!!.nameInSource shouldBe listOf("yy")
assignZZ.target.identifier!!.nameInSource shouldBe listOf("zz")
val valueXXexpr = (assignXX.value as DirectMemoryRead).addressExpression as BinaryExpression
val valueYYexpr = (assignYY.value as DirectMemoryRead).addressExpression as BinaryExpression
val valueZZexpr = (assignZZ.value as DirectMemoryRead).addressExpression as BinaryExpression
assertEquals(listOf("rr"), (valueXXexpr.left as IdentifierReference).nameInSource)
assertEquals(listOf("rr"), (valueYYexpr.left as IdentifierReference).nameInSource)
assertEquals(listOf("other"), (valueZZexpr.left as IdentifierReference).nameInSource)
assertEquals(1, (valueXXexpr.right as NumericLiteralValue).number.toInt())
assertEquals(2, (valueYYexpr.right as NumericLiteralValue).number.toInt())
assertEquals(3, (valueZZexpr.right as NumericLiteralValue).number.toInt())
(valueXXexpr.left as IdentifierReference).nameInSource shouldBe listOf("rr")
(valueYYexpr.left as IdentifierReference).nameInSource shouldBe listOf("rr")
(valueZZexpr.left as IdentifierReference).nameInSource shouldBe listOf("other")
(valueXXexpr.right as NumericLiteralValue).number.toInt() shouldBe 1
(valueYYexpr.right as NumericLiteralValue).number.toInt() shouldBe 2
(valueZZexpr.right as NumericLiteralValue).number.toInt() shouldBe 3
}
test("testUwordParameterAndNormalVarIndexedAsArrayWorkAsMemoryWrite") {
@ -232,15 +250,15 @@ class TestSubroutines: FunSpec({
val module = result.program.toplevelModule
val block = module.statements.single() as Block
val thing = block.statements.filterIsInstance<Subroutine>().single {it.name=="thing"}
assertEquals("main", block.name)
assertEquals(3, thing.statements.size, "rr, rr assign, return void")
block.name shouldBe "main"
thing.statements.size shouldBe 3 // "rr, rr assign, return void"
val assignRR = thing.statements[1] as Assignment
assertEquals(42, (assignRR.value as NumericLiteralValue).number.toInt())
(assignRR.value as NumericLiteralValue).number.toInt() shouldBe 42
val memwrite = assignRR.target.memoryAddress
assertNotNull(memwrite, "memwrite to set byte array value")
val addressExpr = memwrite.addressExpression as BinaryExpression
assertEquals(listOf("rr"), (addressExpr.left as IdentifierReference).nameInSource)
assertEquals("+", addressExpr.operator)
assertEquals(10, (addressExpr.right as NumericLiteralValue).number.toInt())
memwrite shouldNotBe null
val addressExpr = memwrite!!.addressExpression as BinaryExpression
(addressExpr.left as IdentifierReference).nameInSource shouldBe listOf("rr")
addressExpr.operator shouldBe "+"
(addressExpr.right as NumericLiteralValue).number.toInt() shouldBe 10
}
})

View File

@ -18,11 +18,6 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-cli:0.3.3'
implementation "com.github.hypfvieh:dbus-java:3.3.1"
implementation "org.slf4j:slf4j-simple:1.7.30"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit5"
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2'
testImplementation 'org.hamcrest:hamcrest:2.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
}
configurations.all {

View File

@ -22,11 +22,6 @@ dependencies {
implementation "javax.json:javax.json-api:1.1.4"
implementation "org.glassfish:javax.json:1.1.4"
implementation "org.slf4j:slf4j-simple:1.7.30"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit5"
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2'
testImplementation 'org.hamcrest:hamcrest:2.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
}
configurations.all {