diff --git a/compiler/test/TestCompilerOnCharLit.kt b/compiler/test/TestCompilerOnCharLit.kt new file mode 100644 index 000000000..245f9fe39 --- /dev/null +++ b/compiler/test/TestCompilerOnCharLit.kt @@ -0,0 +1,138 @@ +package prog8tests + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import kotlin.test.* +import kotlin.io.path.* + +import prog8.ast.IFunctionCall +import prog8.ast.base.DataType +import prog8.ast.base.VarDeclType +import prog8.ast.expressions.IdentifierReference +import prog8.ast.expressions.NumericLiteralValue +import prog8.compiler.target.Cx16Target + +import prog8.compiler.compileProgram + + +/** + * ATTENTION: this is just kludge! + * They are not really unit tests, but rather tests of the whole process, + * from source file loading all the way through to running 64tass. + * What's more: in case of failure (to compile and assemble) - which is when tests should help you - + * these tests will actually be ignored (ie. NOT fail), + * because in the code there are calls to Process.exit, making it essentially untestable. + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class TestCompilerOnCharLit { + val workingDir = Path("").absolute() // Note: Path(".") does NOT work..! + val fixturesDir = workingDir.resolve("test/fixtures") + val outputDir = workingDir.resolve("build/tmp/test") + + @Test + fun testDirectoriesSanityCheck() { + assertEquals("compiler", workingDir.fileName.toString()) + assertTrue(fixturesDir.isDirectory(), "sanity check; should be directory: $fixturesDir") + assertTrue(outputDir.isDirectory(), "sanity check; should be directory: $outputDir") + } + + @Test + fun testCharLitAsRomsubArg() { + val filepath = fixturesDir.resolve("charLitAsRomsubArg.p8") + val compilationTarget = Cx16Target + val result = compileProgram( + filepath, + optimize = false, + writeAssembly = true, + slowCodegenWarnings = false, + compilationTarget.name, + libdirs = listOf(), + outputDir + ) + assertTrue(result.success, "compilation successful") + + val program = result.programAst + val startSub = program.entrypoint() + val funCall = startSub.statements.filterIsInstance()[0] + + assertIs(funCall.args[0], + "char literal should have been replaced by ubyte literal") + val arg = funCall.args[0] as NumericLiteralValue + assertEquals(DataType.UBYTE, arg.type) + assertEquals(compilationTarget.encodeString("\n", false)[0], arg.number) + } + + @Test + fun testCharVarAsRomsubArg() { + val filepath = fixturesDir.resolve("charVarAsRomsubArg.p8") + val compilationTarget = Cx16Target + val result = compileProgram( + filepath, + optimize = false, + writeAssembly = true, + slowCodegenWarnings = false, + compilationTarget.name, + libdirs = listOf(), + outputDir + ) + assertTrue(result.success, "compilation successful") + val program = result.programAst + val startSub = program.entrypoint() + val funCall = startSub.statements.filterIsInstance()[0] + + assertIs(funCall.args[0]) + val arg = funCall.args[0] as IdentifierReference + val decl = arg.targetVarDecl(program)!! + assertEquals(VarDeclType.VAR, decl.type) + assertEquals(DataType.UBYTE, decl.datatype) + + // TODO: assertIs(decl.value, + // "char literals should be kept until code gen") + // val initializerValue = decl.value as CharLiteral + // assertEquals('\n', (initializerValue as CharLiteral).value) + + assertIs(decl.value, + "char literal should have been replaced by ubyte literal") + val initializerValue = decl.value as NumericLiteralValue + assertEquals(DataType.UBYTE, initializerValue.type) + assertEquals(compilationTarget.encodeString("\n", false)[0], initializerValue.number) + } + + @Test + fun testCharConstAsRomsubArg() { + val filepath = fixturesDir.resolve("charConstAsRomsubArg.p8") + val compilationTarget = Cx16Target + val result = compileProgram( + filepath, + optimize = false, + writeAssembly = true, + slowCodegenWarnings = false, + compilationTarget.name, + libdirs = listOf(), + outputDir + ) + assertTrue(result.success, "compilation successful") + val program = result.programAst + val startSub = program.entrypoint() + val funCall = startSub.statements.filterIsInstance()[0] + + // Now, both is ok for the arg: a) still the IdRef or b) replaced by numeric literal + when (val arg = funCall.args[0]) { + is IdentifierReference -> { + val decl = arg.targetVarDecl(program)!! + assertEquals(VarDeclType.CONST, decl.type) + assertEquals(DataType.UBYTE, decl.datatype) + assertEquals( + compilationTarget.encodeString("\n", false)[0], + (decl.value as NumericLiteralValue).number) + } + is NumericLiteralValue -> { + assertEquals( + compilationTarget.encodeString("\n", false)[0], + arg.number) + } + else -> assertIs(funCall.args[0]) // make test fail + } + + } +} \ No newline at end of file diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt new file mode 100644 index 000000000..4b4107acb --- /dev/null +++ b/compiler/test/TestCompilerOnExamples.kt @@ -0,0 +1,78 @@ +package prog8tests + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import kotlin.test.* +import kotlin.io.path.* + +import prog8.compiler.target.Cx16Target +import prog8.compiler.compileProgram +import prog8.compiler.target.ICompilationTarget + + +/** + * ATTENTION: this is just kludge! + * They are not really unit tests, but rather tests of the whole process, + * from source file loading all the way through to running 64tass. + * What's more: in case of failure (to compile and assemble) - which is when tests should help you - + * these tests will actually be ignored (ie. NOT fail), + * because in the code there are calls to Process.exit, making it essentially untestable. + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class TestCompilerOnExamples { + val workingDir = Path("").absolute() // Note: Path(".") does NOT work..! + val examplesDir = workingDir.resolve("../examples") + val outputDir = workingDir.resolve("build/tmp/test") + + @Test + fun testDirectoriesSanityCheck() { + assertEquals("compiler", workingDir.fileName.toString()) + assertTrue(examplesDir.isDirectory(), "sanity check; should be directory: $examplesDir") + assertTrue(outputDir.isDirectory(), "sanity check; should be directory: $outputDir") + } + + // TODO: make assembly stage testable - in case of failure (eg of 64tass) it Process.exit s + + fun testExample(nameWithoutExt: String, platform: ICompilationTarget, optimize: Boolean) { + val filepath = examplesDir.resolve("$nameWithoutExt.p8") + val result = compileProgram( + filepath, + optimize, + writeAssembly = true, + slowCodegenWarnings = false, + compilationTarget = platform.name, + libdirs = listOf(), + outputDir + ) + assertTrue(result.success, "${platform.name}, optimize=$optimize: \"$filepath\"") + } + + + @Test + fun test_cxLogo_noopt() { + testExample("cxlogo", Cx16Target, false) + } + @Test + fun test_cxLogo_opt() { + testExample("cxlogo", Cx16Target, true) + } + + @Test + fun test_swirl_noopt() { + testExample("swirl", Cx16Target, false) + } + @Test + fun test_swirl_opt() { + testExample("swirl", Cx16Target, true) + } + + @Test + fun test_animals_noopt() { + testExample("animals", Cx16Target, false) + } + @Test + fun test_animals_opt() { + testExample("animals", Cx16Target, true) + } + +} \ No newline at end of file diff --git a/compiler/test/fixtures/charConstAsRomsubArg.p8 b/compiler/test/fixtures/charConstAsRomsubArg.p8 new file mode 100644 index 000000000..838149365 --- /dev/null +++ b/compiler/test/fixtures/charConstAsRomsubArg.p8 @@ -0,0 +1,7 @@ +main { + romsub $FFD2 = chrout(ubyte ch @ A) + sub start() { + const ubyte ch = '\n' + chrout(ch) + } +} diff --git a/compiler/test/fixtures/charLitAsRomsubArg.p8 b/compiler/test/fixtures/charLitAsRomsubArg.p8 new file mode 100644 index 000000000..ebcfa426e --- /dev/null +++ b/compiler/test/fixtures/charLitAsRomsubArg.p8 @@ -0,0 +1,6 @@ +main { + romsub $FFD2 = chrout(ubyte ch @ A) + sub start() { + chrout('\n') + } +} diff --git a/compiler/test/fixtures/charVarAsRomsubArg.p8 b/compiler/test/fixtures/charVarAsRomsubArg.p8 new file mode 100644 index 000000000..e04462345 --- /dev/null +++ b/compiler/test/fixtures/charVarAsRomsubArg.p8 @@ -0,0 +1,7 @@ +main { + romsub $FFD2 = chrout(ubyte ch @ A) + sub start() { + ubyte ch = '\n' + chrout(ch) + } +}