mirror of
				https://github.com/irmen/prog8.git
				synced 2025-10-31 15:16:13 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			130 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Kotlin
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Kotlin
		
	
	
	
	
	
| package prog8tests.compiler
 | |
| 
 | |
| import io.kotest.assertions.fail
 | |
| import io.kotest.assertions.withClue
 | |
| import io.kotest.core.spec.style.FunSpec
 | |
| import io.kotest.engine.spec.tempdir
 | |
| import io.kotest.matchers.shouldBe
 | |
| import io.kotest.matchers.types.instanceOf
 | |
| import prog8.ast.IFunctionCall
 | |
| import prog8.ast.IStatementContainer
 | |
| import prog8.ast.expressions.IdentifierReference
 | |
| import prog8.ast.expressions.NumericLiteral
 | |
| import prog8.ast.statements.Assignment
 | |
| import prog8.ast.statements.AssignmentOrigin
 | |
| import prog8.ast.statements.VarDecl
 | |
| import prog8.ast.statements.VarDeclType
 | |
| import prog8.code.core.BaseDataType
 | |
| import prog8.code.core.DataType
 | |
| import prog8.code.core.Encoding
 | |
| import prog8.code.target.Cx16Target
 | |
| import prog8tests.helpers.compileText
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * 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.
 | |
|  */
 | |
| class TestCompilerOnCharLit: FunSpec({
 | |
| 
 | |
|     val outputDir = tempdir().toPath()
 | |
| 
 | |
|     fun findInitializer(vardecl: VarDecl): Assignment? =
 | |
|         (vardecl.parent as IStatementContainer).statements
 | |
|             .asSequence()
 | |
|             .filterIsInstance<Assignment>()
 | |
|             .singleOrNull { it.origin== AssignmentOrigin.VARINIT && it.target.identifier?.targetVarDecl() === vardecl }
 | |
| 
 | |
| 
 | |
|     test("testCharLitAsExtsubArg") {
 | |
|         val platform = Cx16Target()
 | |
|         val result = compileText(platform, false, """
 | |
|             main {
 | |
|                 extsub ${"$"}FFD2 = chrout(ubyte ch @ A)
 | |
|                 sub start() {
 | |
|                     chrout('\n')
 | |
|                 }
 | |
|             }
 | |
|         """, outputDir)!!
 | |
| 
 | |
|         val program = result.compilerAst
 | |
|         val startSub = program.entrypoint
 | |
|         val funCall = startSub.statements.filterIsInstance<IFunctionCall>()[0]
 | |
| 
 | |
|         withClue("char literal should have been replaced by ubyte literal") {
 | |
|             funCall.args[0] shouldBe instanceOf<NumericLiteral>()
 | |
|         }
 | |
|         val arg = funCall.args[0] as NumericLiteral
 | |
|         arg.type shouldBe BaseDataType.UBYTE
 | |
|         arg.number shouldBe platform.encodeString("\n", Encoding.PETSCII)[0].toDouble()
 | |
|     }
 | |
| 
 | |
|     test("testCharVarAsExtsubArg") {
 | |
|         val platform = Cx16Target()
 | |
|         val result = compileText(platform, false, """
 | |
|             main {
 | |
|                 extsub ${"$"}FFD2 = chrout(ubyte ch @ A)
 | |
|                 sub start() {
 | |
|                     ubyte ch = '\n'
 | |
|                     chrout(ch)
 | |
|                 }
 | |
|             }
 | |
|         """, outputDir)!!
 | |
| 
 | |
|         val program = result.compilerAst
 | |
|         val startSub = program.entrypoint
 | |
|         val funCall = startSub.statements.filterIsInstance<IFunctionCall>()[0]
 | |
| 
 | |
|         funCall.args[0] shouldBe instanceOf<IdentifierReference>()
 | |
|         val arg = funCall.args[0] as IdentifierReference
 | |
|         val decl = arg.targetVarDecl()!!
 | |
|         decl.type shouldBe VarDeclType.VAR
 | |
|         decl.datatype shouldBe DataType.UBYTE
 | |
| 
 | |
|         withClue("initializer value should have been moved to separate assignment"){
 | |
|             decl.value shouldBe null
 | |
|         }
 | |
|         val assignInitialValue = findInitializer(decl)!!
 | |
|         assignInitialValue.target.identifier!!.nameInSource shouldBe listOf("ch")
 | |
|         withClue("char literal should have been replaced by ubyte literal") {
 | |
|             assignInitialValue.value shouldBe instanceOf<NumericLiteral>()
 | |
|         }
 | |
|         val initializerValue = assignInitialValue.value as NumericLiteral
 | |
|         initializerValue.type shouldBe BaseDataType.UBYTE
 | |
|         initializerValue.number shouldBe platform.encodeString("\n", Encoding.PETSCII)[0].toDouble()
 | |
|     }
 | |
| 
 | |
|     test("testCharConstAsExtsubArg") {
 | |
|         val platform = Cx16Target()
 | |
|         val result = compileText(platform, false, """
 | |
|             main {
 | |
|                 extsub ${"$"}FFD2 = chrout(ubyte ch @ A)
 | |
|                 sub start() {
 | |
|                     const ubyte ch = '\n'
 | |
|                     chrout(ch)
 | |
|                 }
 | |
|             }
 | |
|         """, outputDir)!!
 | |
| 
 | |
|         val program = result.compilerAst
 | |
|         val startSub = program.entrypoint
 | |
|         val funCall = startSub.statements.filterIsInstance<IFunctionCall>()[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()!!
 | |
|                 decl.type shouldBe VarDeclType.CONST
 | |
|                 decl.datatype shouldBe DataType.UBYTE
 | |
|                 (decl.value as NumericLiteral).number shouldBe platform.encodeString("\n", Encoding.PETSCII)[0]
 | |
|             }
 | |
|             is NumericLiteral -> {
 | |
|                 arg.number shouldBe platform.encodeString("\n", Encoding.PETSCII)[0].toDouble()
 | |
|             }
 | |
|             else -> fail("invalid arg type") // funCall.args[0] shouldBe instanceOf<IdentifierReference>() // make test fail
 | |
|         }
 | |
|     }
 | |
| 
 | |
| })
 |