diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 5cb3cc0e8..a32d2b5fb 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -1,9 +1,6 @@ package prog8.compiler -import prog8.ast.AstToSourceCode -import prog8.ast.IBuiltinFunctions -import prog8.ast.IMemSizer -import prog8.ast.Program +import prog8.ast.* import prog8.ast.base.AstException import prog8.ast.base.Position import prog8.ast.expressions.Expression @@ -268,6 +265,9 @@ private fun processAst(programAst: Program, errors: IErrorReporter, compilerOpti println("Processing for target ${compilerOptions.compTarget.name}...") programAst.checkIdentifiers(errors, compilerOptions) errors.report() + // TODO: turning char literals into UBYTEs via an encoding should really happen in code gen - but for that we'd need DataType.CHAR + programAst.charLiteralsToUByteLiterals(errors, compilerOptions.compTarget as IStringEncoding) + errors.report() programAst.constantFold(errors, compilerOptions.compTarget) errors.report() programAst.reorderStatements(errors) diff --git a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt index 47579d965..b420be300 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt @@ -1,8 +1,15 @@ package prog8.compiler.astprocessing +import prog8.ast.IStringEncoding +import prog8.ast.Node import prog8.ast.Program +import prog8.ast.base.DataType import prog8.ast.base.FatalAstException +import prog8.ast.expressions.CharLiteral +import prog8.ast.expressions.NumericLiteralValue import prog8.ast.statements.Directive +import prog8.ast.walk.AstWalker +import prog8.ast.walk.IAstModification import prog8.compiler.BeforeAsmGenerationAstChanger import prog8.compiler.CompilationOptions import prog8.compiler.IErrorReporter @@ -33,6 +40,20 @@ internal fun Program.reorderStatements(errors: IErrorReporter) { } } +internal fun Program.charLiteralsToUByteLiterals(errors: IErrorReporter, enc: IStringEncoding) { + val walker = object : AstWalker() { + override fun after(char: CharLiteral, parent: Node): Iterable { + return listOf(IAstModification.ReplaceNode( + char, + NumericLiteralValue(DataType.UBYTE, enc.encodeString(char.value.toString(), char.altEncoding)[0].toInt(), char.position), + parent + )) + } + } + walker.visit(this) + walker.applyModifications() +} + internal fun Program.addTypecasts(errors: IErrorReporter) { val caster = TypecastsAdder(this, errors) caster.visit(this) diff --git a/compiler/test/TestCompilerOnCharLit.kt b/compiler/test/TestCompilerOnCharLit.kt index 2c61ea191..9773aa000 100644 --- a/compiler/test/TestCompilerOnCharLit.kt +++ b/compiler/test/TestCompilerOnCharLit.kt @@ -40,7 +40,7 @@ class TestCompilerOnCharLit { "char literal should have been replaced by ubyte literal") val arg = funCall.args[0] as NumericLiteralValue assertEquals(DataType.UBYTE, arg.type) - assertEquals(platform.encodeString("\n", false)[0], arg.number) + assertEquals(platform.encodeString("\n", false)[0], arg.number.toShort()) // TODO: short/int/UBYTE - which should it be? } @Test @@ -67,7 +67,7 @@ class TestCompilerOnCharLit { "char literal should have been replaced by ubyte literal") val initializerValue = decl.value as NumericLiteralValue assertEquals(DataType.UBYTE, initializerValue.type) - assertEquals(platform.encodeString("\n", false)[0], initializerValue.number) + assertEquals(platform.encodeString("\n", false)[0], initializerValue.number.toShort()) // TODO: short/int/UBYTE - which should it be? } @Test @@ -87,12 +87,12 @@ class TestCompilerOnCharLit { assertEquals(DataType.UBYTE, decl.datatype) assertEquals( platform.encodeString("\n", false)[0], - (decl.value as NumericLiteralValue).number) + (decl.value as NumericLiteralValue).number.toShort()) // TODO: short/int/UBYTE - which should it be? } is NumericLiteralValue -> { assertEquals( platform.encodeString("\n", false)[0], - arg.number) + arg.number.toShort()) // TODO: short/int/UBYTE - which should it be? } else -> assertIs(funCall.args[0]) // make test fail }