diff --git a/codeGeneration/codeGeneration.iml b/codeGeneration/codeGeneration.iml index 9a8fa347e..928636817 100644 --- a/codeGeneration/codeGeneration.iml +++ b/codeGeneration/codeGeneration.iml @@ -5,6 +5,7 @@ + diff --git a/codeGeneration/test/AsmGenTests.kt b/codeGeneration/test/AsmGenTests.kt index dc2711456..323f6f848 100644 --- a/codeGeneration/test/AsmGenTests.kt +++ b/codeGeneration/test/AsmGenTests.kt @@ -21,6 +21,7 @@ import prog8.compilerinterface.* import prog8.parser.SourceCode import prog8tests.asmgen.helpers.DummyFunctions import prog8tests.asmgen.helpers.DummyMemsizer +import prog8tests.asmgen.helpers.DummyStringEncoder import prog8tests.asmgen.helpers.ErrorReporterForTests import java.nio.file.Path @@ -73,7 +74,7 @@ locallabel: val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY) val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test")) - val program = Program("test", DummyFunctions, DummyMemsizer) + val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) module.linkIntoProgram(program) return program diff --git a/codeGeneration/test/helpers/Dummies.kt b/codeGeneration/test/helpers/Dummies.kt index abcf1f8fe..ccb9d10f3 100644 --- a/codeGeneration/test/helpers/Dummies.kt +++ b/codeGeneration/test/helpers/Dummies.kt @@ -7,6 +7,7 @@ import prog8.ast.expressions.InferredTypes import prog8.ast.expressions.NumericLiteralValue import prog8.compilerinterface.IMemSizer import prog8.ast.base.DataType +import prog8.compilerinterface.IStringEncoding internal val DummyFunctions = object : IBuiltinFunctions { @@ -24,3 +25,13 @@ internal val DummyFunctions = object : IBuiltinFunctions { internal val DummyMemsizer = object : IMemSizer { override fun memorySize(dt: DataType): Int = 0 } + +internal val DummyStringEncoder = object : IStringEncoding { + override fun encodeString(str: String, altEncoding: Boolean): List { + return emptyList() + } + + override fun decodeString(bytes: List, altEncoding: Boolean): String { + return "" + } +} diff --git a/codeOptimizers/codeOptimizers.iml b/codeOptimizers/codeOptimizers.iml index 6778075ca..45621612e 100644 --- a/codeOptimizers/codeOptimizers.iml +++ b/codeOptimizers/codeOptimizers.iml @@ -5,6 +5,7 @@ + diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index c09a9ef4f..84ec61cbb 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -115,7 +115,7 @@ fun compileProgram(filepath: Path, throw x } - val failedProgram = Program("failed", BuiltinFunctionsFacade(BuiltinFunctions), compTarget) + val failedProgram = Program("failed", BuiltinFunctionsFacade(BuiltinFunctions), compTarget, compTarget) return CompilationResult(false, failedProgram, programName, compTarget, emptyList()) } @@ -155,7 +155,7 @@ fun parseImports(filepath: Path, sourceDirs: List): Triple> { println("Compiler target: ${compTarget.name}. Parsing...") val bf = BuiltinFunctionsFacade(BuiltinFunctions) - val programAst = Program(filepath.nameWithoutExtension, bf, compTarget) + val programAst = Program(filepath.nameWithoutExtension, bf, compTarget, compTarget) bf.program = programAst val importer = ModuleImporter(programAst, compTarget.name, errors, sourceDirs) diff --git a/compiler/test/ModuleImporterTests.kt b/compiler/test/ModuleImporterTests.kt index fb7714c19..e9e6098b3 100644 --- a/compiler/test/ModuleImporterTests.kt +++ b/compiler/test/ModuleImporterTests.kt @@ -17,6 +17,7 @@ import prog8tests.ast.helpers.* import prog8tests.helpers.ErrorReporterForTests import prog8tests.helpers.DummyFunctions import prog8tests.helpers.DummyMemsizer +import prog8tests.helpers.DummyStringEncoder import kotlin.io.path.* import kotlin.test.assertContains import kotlin.test.assertFailsWith @@ -31,7 +32,7 @@ class TestModuleImporter { private lateinit var program: Program @BeforeEach fun beforeEach() { - program = Program("foo", DummyFunctions, DummyMemsizer) + program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder) } private fun makeImporter(errors: IErrorReporter?, vararg searchIn: String): ModuleImporter { diff --git a/compiler/test/TestMemory.kt b/compiler/test/TestMemory.kt index c75d8c4b9..ac21d098f 100644 --- a/compiler/test/TestMemory.kt +++ b/compiler/test/TestMemory.kt @@ -17,6 +17,7 @@ import prog8.compilerinterface.isInRegularRAMof import prog8.parser.SourceCode import prog8tests.helpers.DummyFunctions import prog8tests.helpers.DummyMemsizer +import prog8tests.helpers.DummyStringEncoder import kotlin.test.assertFalse import kotlin.test.assertTrue @@ -70,7 +71,7 @@ class TestMemory { @Test fun testInValidRamC64_memory_identifiers() { - val program = Program("test", DummyFunctions, DummyMemsizer) + val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) var target = createTestProgramForMemoryRefViaVar(program, 0x1000, VarDeclType.VAR) assertTrue(target.isInRegularRAMof(C64Target.machine)) @@ -109,7 +110,7 @@ class TestMemory { val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) - val program = Program("test", DummyFunctions, DummyMemsizer) + val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) module.linkIntoProgram(program) assertTrue(target.isInRegularRAMof(C64Target.machine)) @@ -123,7 +124,7 @@ class TestMemory { val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) - val program = Program("test", DummyFunctions, DummyMemsizer) + val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) module.linkIntoProgram(program) assertTrue(target.isInRegularRAMof(C64Target.machine)) @@ -137,7 +138,7 @@ class TestMemory { val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) - val program = Program("test", DummyFunctions, DummyMemsizer) + val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) module.linkIntoProgram(program) assertFalse(target.isInRegularRAMof(C64Target.machine)) @@ -151,7 +152,7 @@ class TestMemory { val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) - val program = Program("test", DummyFunctions, DummyMemsizer) + val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) module.linkIntoProgram(program) assertTrue(target.isInRegularRAMof(C64Target.machine)) @@ -166,7 +167,7 @@ class TestMemory { val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) - val program = Program("test", DummyFunctions, DummyMemsizer) + val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) module.linkIntoProgram(program) assertTrue(target.isInRegularRAMof(C64Target.machine)) @@ -181,7 +182,7 @@ class TestMemory { val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY) val subroutine = Subroutine("test", mutableListOf(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, false, mutableListOf(decl, assignment), Position.DUMMY) val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test")) - val program = Program("test", DummyFunctions, DummyMemsizer) + val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) module.linkIntoProgram(program) assertFalse(target.isInRegularRAMof(C64Target.machine)) diff --git a/compiler/test/helpers/Dummies.kt b/compiler/test/helpers/Dummies.kt index c0209f950..9a8128584 100644 --- a/compiler/test/helpers/Dummies.kt +++ b/compiler/test/helpers/Dummies.kt @@ -7,6 +7,7 @@ import prog8.ast.expressions.Expression import prog8.ast.expressions.InferredTypes import prog8.ast.expressions.NumericLiteralValue import prog8.compilerinterface.IMemSizer +import prog8.compilerinterface.IStringEncoding internal val DummyFunctions = object : IBuiltinFunctions { override val names: Set = emptySet() @@ -23,3 +24,13 @@ internal val DummyFunctions = object : IBuiltinFunctions { internal val DummyMemsizer = object : IMemSizer { override fun memorySize(dt: DataType): Int = 0 } + +internal val DummyStringEncoder = object : IStringEncoding { + override fun encodeString(str: String, altEncoding: Boolean): List { + return emptyList() + } + + override fun decodeString(bytes: List, altEncoding: Boolean): String { + return "" + } +} diff --git a/compilerAst/src/prog8/ast/AstToplevel.kt b/compilerAst/src/prog8/ast/AstToplevel.kt index 91d97cab7..9f34ad87b 100644 --- a/compilerAst/src/prog8/ast/AstToplevel.kt +++ b/compilerAst/src/prog8/ast/AstToplevel.kt @@ -8,6 +8,7 @@ import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstVisitor import prog8.compilerinterface.IMemSizer +import prog8.compilerinterface.IStringEncoding import prog8.parser.SourceCode const val internedStringsModuleName = "prog8_interned_strings" @@ -287,7 +288,8 @@ interface Node { class Program(val name: String, val builtinFunctions: IBuiltinFunctions, - val memsizer: IMemSizer + val memsizer: IMemSizer, + val encoding: IStringEncoding ): Node { private val _modules = mutableListOf() diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 5a47e0665..827599fcf 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -514,7 +514,10 @@ class CharLiteral(val value: Char, } override fun referencesIdentifier(vararg scopedName: String) = false - override fun constValue(program: Program): NumericLiteralValue? = null // TODO: CharLiteral.constValue can't be NumericLiteralValue... unless we re-add string encoder to program? + override fun constValue(program: Program): NumericLiteralValue { + val bytevalue = program.encoding.encodeString(value.toString(), altEncoding).single() + return NumericLiteralValue(DataType.UBYTE, bytevalue, position) + } override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) diff --git a/compilerInterfaces/src/prog8/compilerinterface/IStringEncoding.kt b/compilerAst/src/prog8/compilerinterface/IStringEncoding.kt similarity index 100% rename from compilerInterfaces/src/prog8/compilerinterface/IStringEncoding.kt rename to compilerAst/src/prog8/compilerinterface/IStringEncoding.kt diff --git a/compilerAst/test/TestAstToSourceText.kt b/compilerAst/test/TestAstToSourceText.kt index 20ccc0f40..b322e0b1a 100644 --- a/compilerAst/test/TestAstToSourceText.kt +++ b/compilerAst/test/TestAstToSourceText.kt @@ -11,6 +11,7 @@ import prog8.parser.Prog8Parser.parseModule import prog8.parser.SourceCode import prog8tests.ast.helpers.DummyFunctions import prog8tests.ast.helpers.DummyMemsizer +import prog8tests.ast.helpers.DummyStringEncoder import kotlin.test.assertContains @@ -18,7 +19,7 @@ import kotlin.test.assertContains class TestAstToSourceText { private fun generateP8(module: Module) : String { - val program = Program("test", DummyFunctions, DummyMemsizer) + val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder) .addModule(module) var generatedText = "" diff --git a/compilerAst/test/TestProg8Parser.kt b/compilerAst/test/TestProg8Parser.kt index 4c442f263..73f87a1d9 100644 --- a/compilerAst/test/TestProg8Parser.kt +++ b/compilerAst/test/TestProg8Parser.kt @@ -6,6 +6,7 @@ import org.junit.jupiter.api.TestInstance import prog8.ast.IFunctionCall import prog8.ast.Module import prog8.ast.Node +import prog8.ast.Program import prog8.ast.base.DataType import prog8.ast.base.Position import prog8.ast.expressions.CharLiteral @@ -16,9 +17,9 @@ import prog8.ast.statements.* import prog8.parser.ParseError import prog8.parser.Prog8Parser.parseModule import prog8.parser.SourceCode -import prog8tests.ast.helpers.assumeNotExists -import prog8tests.ast.helpers.assumeReadableFile -import prog8tests.ast.helpers.fixturesDir +import prog8tests.ast.helpers.* +import prog8tests.ast.helpers.DummyFunctions +import prog8tests.ast.helpers.DummyMemsizer import kotlin.io.path.Path import kotlin.io.path.isRegularFile import kotlin.io.path.name @@ -582,6 +583,16 @@ class TestProg8Parser { } } + @Test + fun testCharLiteralConstValue() { + val char1 = CharLiteral('A', false, Position.DUMMY) + val char2 = CharLiteral('z', true, Position.DUMMY) + + val program = Program("test", DummyFunctions, DummyMemsizer, AsciiStringEncoder) + assertEquals(65, char1.constValue(program).number.toInt()) + assertEquals(122, char2.constValue(program).number.toInt()) + } + @Test fun testLiteralValueComparisons() { val ten = NumericLiteralValue(DataType.UWORD, 10, Position.DUMMY) diff --git a/compilerAst/test/ast/ProgramTests.kt b/compilerAst/test/ast/ProgramTests.kt index 6694ab6fa..27896f26e 100644 --- a/compilerAst/test/ast/ProgramTests.kt +++ b/compilerAst/test/ast/ProgramTests.kt @@ -1,6 +1,5 @@ package prog8tests.ast.ast - import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.containsString import org.hamcrest.Matchers.equalTo @@ -14,6 +13,7 @@ import prog8.ast.internedStringsModuleName import prog8.parser.SourceCode import prog8tests.ast.helpers.DummyFunctions import prog8tests.ast.helpers.DummyMemsizer +import prog8tests.ast.helpers.DummyStringEncoder import kotlin.test.assertContains import kotlin.test.assertFailsWith import kotlin.test.assertSame @@ -26,7 +26,7 @@ class ProgramTests { inner class Constructor { @Test fun withNameBuiltinsAndMemsizer() { - val program = Program("foo", DummyFunctions, DummyMemsizer) + val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder) assertThat(program.modules.size, equalTo(1)) assertThat(program.modules[0].name, equalTo(internedStringsModuleName)) assertSame(program, program.modules[0].program) @@ -39,7 +39,7 @@ class ProgramTests { inner class AddModule { @Test fun withEmptyModule() { - val program = Program("foo", DummyFunctions, DummyMemsizer) + val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder) val m1 = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("bar")) val retVal = program.addModule(m1) @@ -63,7 +63,7 @@ class ProgramTests { inner class MoveModuleToFront { @Test fun withInternedStringsModule() { - val program = Program("foo", DummyFunctions, DummyMemsizer) + val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder) val m = program.modules[0] assertThat(m.name, equalTo(internedStringsModuleName)) @@ -73,14 +73,14 @@ class ProgramTests { } @Test fun withForeignModule() { - val program = Program("foo", DummyFunctions, DummyMemsizer) + val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder) val m = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("bar")) assertFailsWith { program.moveModuleToFront(m) } } @Test fun withFirstOfPreviouslyAddedModules() { - val program = Program("foo", DummyFunctions, DummyMemsizer) + val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder) val m1 = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("bar")) val m2 = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("qmbl")) program.addModule(m1) @@ -92,7 +92,7 @@ class ProgramTests { } @Test fun withSecondOfPreviouslyAddedModules() { - val program = Program("foo", DummyFunctions, DummyMemsizer) + val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder) val m1 = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("bar")) val m2 = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("qmbl")) program.addModule(m1) @@ -108,7 +108,7 @@ class ProgramTests { inner class Properties { @Test fun modules() { - val program = Program("foo", DummyFunctions, DummyMemsizer) + val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder) val ms1 = program.modules val ms2 = program.modules diff --git a/compilerAst/test/helpers/Dummies.kt b/compilerAst/test/helpers/Dummies.kt index b0e2148f5..fa59a2d51 100644 --- a/compilerAst/test/helpers/Dummies.kt +++ b/compilerAst/test/helpers/Dummies.kt @@ -7,6 +7,7 @@ import prog8.ast.expressions.Expression import prog8.ast.expressions.InferredTypes import prog8.ast.expressions.NumericLiteralValue import prog8.compilerinterface.IMemSizer +import prog8.compilerinterface.IStringEncoding internal val DummyFunctions = object : IBuiltinFunctions { override val names: Set = emptySet() @@ -23,3 +24,21 @@ internal val DummyFunctions = object : IBuiltinFunctions { internal val DummyMemsizer = object : IMemSizer { override fun memorySize(dt: DataType): Int = 0 } + +internal val DummyStringEncoder = object : IStringEncoding { + override fun encodeString(str: String, altEncoding: Boolean): List { + return emptyList() + } + + override fun decodeString(bytes: List, altEncoding: Boolean): String { + return "" + } +} + +internal val AsciiStringEncoder = object : IStringEncoding { + override fun encodeString(str: String, altEncoding: Boolean): List = str.map { it.code.toShort() } + + override fun decodeString(bytes: List, altEncoding: Boolean): String { + return bytes.joinToString() + } +} diff --git a/compilerInterfaces/compilerInterfaces.iml b/compilerInterfaces/compilerInterfaces.iml index 2c25b13e2..31645176c 100644 --- a/compilerInterfaces/compilerInterfaces.iml +++ b/compilerInterfaces/compilerInterfaces.iml @@ -5,6 +5,7 @@ +