char encodings now use UByte type instead of short

This commit is contained in:
Irmen de Jong 2021-11-21 00:07:17 +01:00
parent 2491509c6a
commit c0035ba1a2
14 changed files with 201 additions and 179 deletions

View File

@ -13,14 +13,14 @@ import prog8.compilerinterface.ICompilationTarget
object C64Target: ICompilationTarget { object C64Target: ICompilationTarget {
override val name = "c64" override val name = "c64"
override val machine = C64MachineDefinition override val machine = C64MachineDefinition
override fun encodeString(str: String, altEncoding: Boolean): List<Short> { override fun encodeString(str: String, altEncoding: Boolean): List<UByte> {
val coded = if (altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true) val coded = if (altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
return coded.fold( return coded.fold(
failure = { throw it }, failure = { throw it },
success = { it } success = { it }
) )
} }
override fun decodeString(bytes: List<Short>, altEncoding: Boolean) = override fun decodeString(bytes: List<UByte>, altEncoding: Boolean) =
if (altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true) if (altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
override fun memorySize(dt: DataType): Int { override fun memorySize(dt: DataType): Int {

View File

@ -13,14 +13,14 @@ import prog8.compilerinterface.ICompilationTarget
object Cx16Target: ICompilationTarget { object Cx16Target: ICompilationTarget {
override val name = "cx16" override val name = "cx16"
override val machine = CX16MachineDefinition override val machine = CX16MachineDefinition
override fun encodeString(str: String, altEncoding: Boolean): List<Short> { override fun encodeString(str: String, altEncoding: Boolean): List<UByte> {
val coded= if (altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true) val coded= if (altEncoding) Petscii.encodeScreencode(str, true) else Petscii.encodePetscii(str, true)
return coded.fold( return coded.fold(
failure = { throw it }, failure = { throw it },
success = { it } success = { it }
) )
} }
override fun decodeString(bytes: List<Short>, altEncoding: Boolean) = override fun decodeString(bytes: List<UByte>, altEncoding: Boolean) =
if (altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true) if (altEncoding) Petscii.decodeScreencode(bytes, true) else Petscii.decodePetscii(bytes, true)
override fun memorySize(dt: DataType): Int { override fun memorySize(dt: DataType): Int {

View File

@ -1065,15 +1065,15 @@ object Petscii {
else -> chr else -> chr
} }
fun encodePetscii(text: String, lowercase: Boolean = false): Result<List<Short>, CharConversionException> { fun encodePetscii(text: String, lowercase: Boolean = false): Result<List<UByte>, CharConversionException> {
fun encodeChar(chr3: Char, lowercase: Boolean): Short { fun encodeChar(chr3: Char, lowercase: Boolean): UByte {
val chr = replaceSpecial(chr3) val chr = replaceSpecial(chr3)
val screencode = if(lowercase) encodingPetsciiLowercase[chr] else encodingPetsciiUppercase[chr] val screencode = if(lowercase) encodingPetsciiLowercase[chr] else encodingPetsciiUppercase[chr]
return screencode?.toShort() ?: when (chr) { return screencode?.toUByte() ?: when (chr) {
'\u0000' -> 0.toShort() '\u0000' -> 0u
in '\u8000'..'\u80ff' -> { in '\u8000'..'\u80ff' -> {
// special case: take the lower 8 bit hex value directly // special case: take the lower 8 bit hex value directly
(chr.code - 0x8000).toShort() (chr.code - 0x8000).toUByte()
} }
else -> { else -> {
val case = if (lowercase) "lower" else "upper" val case = if (lowercase) "lower" else "upper"
@ -1095,7 +1095,7 @@ object Petscii {
} }
} }
fun decodePetscii(petscii: Iterable<Short>, lowercase: Boolean = false): String { fun decodePetscii(petscii: Iterable<UByte>, lowercase: Boolean = false): String {
return petscii.map { return petscii.map {
val code = it.toInt() val code = it.toInt()
if(code<0 || code>= decodingPetsciiLowercase.size) if(code<0 || code>= decodingPetsciiLowercase.size)
@ -1104,15 +1104,15 @@ object Petscii {
}.joinToString("") }.joinToString("")
} }
fun encodeScreencode(text: String, lowercase: Boolean = false): Result<List<Short>, CharConversionException> { fun encodeScreencode(text: String, lowercase: Boolean = false): Result<List<UByte>, CharConversionException> {
fun encodeChar(chr3: Char, lowercase: Boolean): Short { fun encodeChar(chr3: Char, lowercase: Boolean): UByte {
val chr = replaceSpecial(chr3) val chr = replaceSpecial(chr3)
val screencode = if(lowercase) encodingScreencodeLowercase[chr] else encodingScreencodeUppercase[chr] val screencode = if(lowercase) encodingScreencodeLowercase[chr] else encodingScreencodeUppercase[chr]
return screencode?.toShort() ?: when (chr) { return screencode?.toUByte() ?: when (chr) {
'\u0000' -> 0.toShort() '\u0000' -> 0u
in '\u8000'..'\u80ff' -> { in '\u8000'..'\u80ff' -> {
// special case: take the lower 8 bit hex value directly // special case: take the lower 8 bit hex value directly
(chr.code - 0x8000).toShort() (chr.code - 0x8000).toUByte()
} }
else -> { else -> {
val case = if (lowercase) "lower" else "upper" val case = if (lowercase) "lower" else "upper"
@ -1134,7 +1134,7 @@ object Petscii {
} }
} }
fun decodeScreencode(screencode: Iterable<Short>, lowercase: Boolean = false): String { fun decodeScreencode(screencode: Iterable<UByte>, lowercase: Boolean = false): String {
return screencode.map { return screencode.map {
val code = it.toInt() val code = it.toInt()
if(code<0 || code>= decodingScreencodeLowercase.size) if(code<0 || code>= decodingScreencodeLowercase.size)
@ -1143,38 +1143,37 @@ object Petscii {
}.joinToString("") }.joinToString("")
} }
fun petscii2scr(petscii_code: Short, inverseVideo: Boolean): Result<Short, CharConversionException> { fun petscii2scr(petscii_code: UByte, inverseVideo: Boolean): Result<UByte, CharConversionException> {
val code = when { val code: UInt = when {
petscii_code < 0 -> return Err(CharConversionException("petscii code out of range")) petscii_code <= 0x1fu -> petscii_code + 128u
petscii_code <= 0x1f -> petscii_code + 128 petscii_code <= 0x3fu -> petscii_code.toUInt()
petscii_code <= 0x3f -> petscii_code.toInt() petscii_code <= 0x5fu -> petscii_code - 64u
petscii_code <= 0x5f -> petscii_code - 64 petscii_code <= 0x7fu -> petscii_code - 32u
petscii_code <= 0x7f -> petscii_code - 32 petscii_code <= 0x9fu -> petscii_code + 64u
petscii_code <= 0x9f -> petscii_code + 64 petscii_code <= 0xbfu -> petscii_code - 64u
petscii_code <= 0xbf -> petscii_code - 64 petscii_code <= 0xfeu -> petscii_code - 128u
petscii_code <= 0xfe -> petscii_code - 128 petscii_code == 255.toUByte() -> 95u
petscii_code == 255.toShort() -> 95
else -> return Err(CharConversionException("petscii code out of range")) else -> return Err(CharConversionException("petscii code out of range"))
} }
if(inverseVideo) if(inverseVideo) {
return Ok((code or 0x80).toShort()) return Ok((code or 0x80u).toUByte())
return Ok(code.toShort()) }
return Ok(code.toUByte())
} }
fun scr2petscii(screencode: Short): Result<Short, CharConversionException> { fun scr2petscii(screencode: UByte): Result<UByte, CharConversionException> {
val petscii = when { val petscii: UInt = when {
screencode < 0 -> return Err(CharConversionException("screencode out of range")) screencode <= 0x1fu -> screencode + 64u
screencode <= 0x1f -> screencode + 64 screencode <= 0x3fu -> screencode.toUInt()
screencode <= 0x3f -> screencode.toInt() screencode <= 0x5du -> screencode +123u
screencode <= 0x5d -> screencode +123 screencode == 0x5e.toUByte() -> 255u
screencode == 0x5e.toShort() -> 255 screencode == 0x5f.toUByte() -> 223u
screencode == 0x5f.toShort() -> 223 screencode <= 0x7fu -> screencode + 64u
screencode <= 0x7f -> screencode + 64 screencode <= 0xbfu -> screencode - 128u
screencode <= 0xbf -> screencode - 128 screencode <= 0xfeu -> screencode - 64u
screencode <= 0xfe -> screencode - 64 screencode == 255.toUByte() -> 191u
screencode == 255.toShort() -> 191
else -> return Err(CharConversionException("screencode out of range")) else -> return Err(CharConversionException("screencode out of range"))
} }
return Ok(petscii.toShort()) return Ok(petscii.toUByte())
} }
} }

View File

@ -297,7 +297,7 @@ class AsmGen(private val program: Program,
DataType.FLOAT -> out("$name\t.byte 0,0,0,0,0 ; float") DataType.FLOAT -> out("$name\t.byte 0,0,0,0,0 ; float")
DataType.STR -> { DataType.STR -> {
val str = decl.value as StringLiteralValue val str = decl.value as StringLiteralValue
outputStringvar(decl, compTarget.encodeString(str.value, str.altEncoding).plus(0)) outputStringvar(decl, compTarget.encodeString(str.value, str.altEncoding).plus(0.toUByte()))
} }
DataType.ARRAY_UB -> { DataType.ARRAY_UB -> {
val data = makeArrayFillDataUnsigned(decl) val data = makeArrayFillDataUnsigned(decl)
@ -393,7 +393,7 @@ class AsmGen(private val program: Program,
.filter {it.datatype == DataType.STR } .filter {it.datatype == DataType.STR }
.map { .map {
val str = it.value as StringLiteralValue val str = it.value as StringLiteralValue
it to compTarget.encodeString(str.value, str.altEncoding).plus(0) it to compTarget.encodeString(str.value, str.altEncoding).plus(0.toUByte())
} }
for((decl, variables) in encodedstringVars) { for((decl, variables) in encodedstringVars) {
outputStringvar(decl, variables) outputStringvar(decl, variables)
@ -410,7 +410,7 @@ class AsmGen(private val program: Program,
} }
} }
private fun outputStringvar(strdecl: VarDecl, bytes: List<Short>) { private fun outputStringvar(strdecl: VarDecl, bytes: List<UByte>) {
val sv = strdecl.value as StringLiteralValue val sv = strdecl.value as StringLiteralValue
val altEncoding = if(sv.altEncoding) "@" else "" val altEncoding = if(sv.altEncoding) "@" else ""
out("${strdecl.name}\t; ${strdecl.datatype} $altEncoding\"${escape(sv.value).replace("\u0000", "<NULL>")}\"") out("${strdecl.name}\t; ${strdecl.datatype} $altEncoding\"${escape(sv.value).replace("\u0000", "<NULL>")}\"")

View File

@ -27,11 +27,11 @@ internal val DummyMemsizer = object : IMemSizer {
} }
internal val DummyStringEncoder = object : IStringEncoding { internal val DummyStringEncoder = object : IStringEncoding {
override fun encodeString(str: String, altEncoding: Boolean): List<Short> { override fun encodeString(str: String, altEncoding: Boolean): List<UByte> {
return emptyList() return emptyList()
} }
override fun decodeString(bytes: List<Short>, altEncoding: Boolean): String { override fun decodeString(bytes: List<UByte>, altEncoding: Boolean): String {
return "" return ""
} }
} }

View File

@ -43,7 +43,7 @@ class TestCompilerOnCharLit: FunSpec({
} }
val arg = funCall.args[0] as NumericLiteralValue val arg = funCall.args[0] as NumericLiteralValue
arg.type shouldBe DataType.UBYTE arg.type shouldBe DataType.UBYTE
arg.number shouldBe platform.encodeString("\n", false)[0] arg.number shouldBe platform.encodeString("\n", false)[0].toDouble()
} }
test("testCharVarAsRomsubArg") { test("testCharVarAsRomsubArg") {
@ -83,7 +83,7 @@ class TestCompilerOnCharLit: FunSpec({
} }
val initializerValue = assignInitialValue.value as NumericLiteralValue val initializerValue = assignInitialValue.value as NumericLiteralValue
initializerValue.type shouldBe DataType.UBYTE initializerValue.type shouldBe DataType.UBYTE
initializerValue.number shouldBe platform.encodeString("\n", false)[0] initializerValue.number shouldBe platform.encodeString("\n", false)[0].toDouble()
} }
test("testCharConstAsRomsubArg") { test("testCharConstAsRomsubArg") {
@ -111,7 +111,7 @@ class TestCompilerOnCharLit: FunSpec({
(decl.value as NumericLiteralValue).number shouldBe platform.encodeString("\n", false)[0] (decl.value as NumericLiteralValue).number shouldBe platform.encodeString("\n", false)[0]
} }
is NumericLiteralValue -> { is NumericLiteralValue -> {
arg.number shouldBe platform.encodeString("\n", false)[0] arg.number shouldBe platform.encodeString("\n", false)[0].toDouble()
} }
else -> fail("invalid arg type") // funCall.args[0] shouldBe instanceOf<IdentifierReference>() // make test fail else -> fail("invalid arg type") // funCall.args[0] shouldBe instanceOf<IdentifierReference>() // make test fail
} }

View File

@ -3,73 +3,71 @@ package prog8tests
import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Ok
import com.github.michaelbull.result.expectError import com.github.michaelbull.result.expectError
import com.github.michaelbull.result.getOrElse import com.github.michaelbull.result.getOrElse
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.assertions.withClue import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import prog8.compiler.target.cbm.Petscii import prog8.compiler.target.cbm.Petscii
import java.io.CharConversionException
class TestPetscii: FunSpec({ class TestPetscii: FunSpec({
test("testZero") { test("testZero") {
Petscii.encodePetscii("\u0000", true) shouldBe Ok(listOf<Short>(0)) Petscii.encodePetscii("\u0000", true) shouldBe Ok(listOf<UByte>(0u))
Petscii.encodePetscii("\u0000", false) shouldBe Ok(listOf<Short>(0)) Petscii.encodePetscii("\u0000", false) shouldBe Ok(listOf<UByte>(0u))
Petscii.decodePetscii(listOf(0), true) shouldBe "\u0000" Petscii.decodePetscii(listOf(0u), true) shouldBe "\u0000"
Petscii.decodePetscii(listOf(0), false) shouldBe "\u0000" Petscii.decodePetscii(listOf(0u), false) shouldBe "\u0000"
} }
test("testLowercase") { test("testLowercase") {
Petscii.encodePetscii("hello WORLD 123 @!£", true) shouldBe 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)) Ok(listOf<UByte>(72u, 69u, 76u, 76u, 79u, 32u, 0xd7u, 0xcfu, 0xd2u, 0xccu, 0xc4u, 32u, 49u, 50u, 51u, 32u, 64u, 33u, 0x5cu))
Petscii.encodePetscii("\uf11a", true) shouldBe Ok(listOf<Short>(0x12)) // reverse vid Petscii.encodePetscii("\uf11a", true) shouldBe Ok(listOf<UByte>(0x12u)) // reverse vid
Petscii.encodePetscii("", true) shouldBe Ok(listOf<Short>(0xfa)) Petscii.encodePetscii("", true) shouldBe Ok(listOf<UByte>(0xfau))
withClue("expect lowercase error fallback") { withClue("expect lowercase error fallback") {
Petscii.encodePetscii("π", true) shouldBe Ok(listOf<Short>(255)) Petscii.encodePetscii("π", true) shouldBe Ok(listOf<UByte>(255u))
Petscii.encodePetscii("", true) shouldBe Ok(listOf<Short>(0xd3)) Petscii.encodePetscii("", true) shouldBe Ok(listOf<UByte>(0xd3u))
} }
Petscii.decodePetscii(listOf(72, 0xd7, 0x5c, 0xfa, 0x12), true) shouldBe "hW£✓\uF11A" Petscii.decodePetscii(listOf(72u, 0xd7u, 0x5cu, 0xfau, 0x12u), true) shouldBe "hW£✓\uF11A"
} }
test("testUppercase") { test("testUppercase") {
Petscii.encodePetscii("HELLO 123 @!£") shouldBe Petscii.encodePetscii("HELLO 123 @!£") shouldBe
Ok(listOf<Short>(72, 69, 76, 76, 79, 32, 49, 50, 51, 32, 64, 33, 0x5c)) Ok(listOf<UByte>(72u, 69u, 76u, 76u, 79u, 32u, 49u, 50u, 51u, 32u, 64u, 33u, 0x5cu))
Petscii.encodePetscii("\uf11a") shouldBe Ok(listOf<Short>(0x12)) // reverse vid Petscii.encodePetscii("\uf11a") shouldBe Ok(listOf<UByte>(0x12u)) // reverse vid
Petscii.encodePetscii("") shouldBe Ok(listOf<Short>(0xd3)) Petscii.encodePetscii("") shouldBe Ok(listOf<UByte>(0xd3u))
Petscii.encodePetscii("π") shouldBe Ok(listOf<Short>(0xff)) Petscii.encodePetscii("π") shouldBe Ok(listOf<UByte>(0xffu))
withClue("expecting fallback") { withClue("expecting fallback") {
Petscii.encodePetscii("") shouldBe Ok(listOf<Short>(250)) Petscii.encodePetscii("") shouldBe Ok(listOf<UByte>(250u))
} }
Petscii.decodePetscii(listOf(72, 0x5c, 0xd3, 0xff)) shouldBe "H£♥π" Petscii.decodePetscii(listOf(72u, 0x5cu, 0xd3u, 0xffu)) shouldBe "H£♥π"
} }
test("testScreencodeLowercase") { test("testScreencodeLowercase") {
Petscii.encodeScreencode("hello WORLD 123 @!£", true) shouldBe 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)) Ok(listOf<UByte>(0x08u, 0x05u, 0x0cu, 0x0cu, 0x0fu, 0x20u, 0x57u, 0x4fu, 0x52u, 0x4cu, 0x44u, 0x20u, 0x31u, 0x32u, 0x33u, 0x20u, 0x00u, 0x21u, 0x1cu))
Petscii.encodeScreencode("", true) shouldBe Ok(listOf<Short>(0x7a)) Petscii.encodeScreencode("", true) shouldBe Ok(listOf<UByte>(0x7au))
withClue("expect fallback") { withClue("expect fallback") {
Petscii.encodeScreencode("", true) shouldBe Ok(listOf<Short>(83)) Petscii.encodeScreencode("", true) shouldBe Ok(listOf<UByte>(83u))
Petscii.encodeScreencode("π", true) shouldBe Ok(listOf<Short>(94)) Petscii.encodeScreencode("π", true) shouldBe Ok(listOf<UByte>(94u))
} }
Petscii.decodeScreencode(listOf(0x08, 0x57, 0x1c, 0x7a), true) shouldBe "hW£✓" Petscii.decodeScreencode(listOf(0x08u, 0x57u, 0x1cu, 0x7au), true) shouldBe "hW£✓"
} }
test("testScreencodeUppercase") { test("testScreencodeUppercase") {
Petscii.encodeScreencode("WORLD 123 @!£") shouldBe Petscii.encodeScreencode("WORLD 123 @!£") shouldBe
Ok(listOf<Short>(0x17, 0x0f, 0x12, 0x0c, 0x04, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c)) Ok(listOf<UByte>(0x17u, 0x0fu, 0x12u, 0x0cu, 0x04u, 0x20u, 0x31u, 0x32u, 0x33u, 0x20u, 0x00u, 0x21u, 0x1cu))
Petscii.encodeScreencode("") shouldBe Ok(listOf<Short>(0x53)) Petscii.encodeScreencode("") shouldBe Ok(listOf<UByte>(0x53u))
Petscii.encodeScreencode("π") shouldBe Ok(listOf<Short>(0x5e)) Petscii.encodeScreencode("π") shouldBe Ok(listOf<UByte>(0x5eu))
Petscii.encodeScreencode("HELLO") shouldBe Ok(listOf<Short>(8, 5, 12, 12, 15)) Petscii.encodeScreencode("HELLO") shouldBe Ok(listOf<UByte>(8u, 5u, 12u, 12u, 15u))
withClue("expecting fallback") { withClue("expecting fallback") {
Petscii.encodeScreencode("hello") shouldBe Ok(listOf<Short>(8, 5, 12, 12, 15)) Petscii.encodeScreencode("hello") shouldBe Ok(listOf<UByte>(8u, 5u, 12u, 12u, 15u))
Petscii.encodeScreencode("") shouldBe Ok(listOf<Short>(122)) Petscii.encodeScreencode("") shouldBe Ok(listOf<UByte>(122u))
} }
Petscii.decodeScreencode(listOf(0x17, 0x1c, 0x53, 0x5e)) shouldBe "W£♥π" Petscii.decodeScreencode(listOf(0x17u, 0x1cu, 0x53u, 0x5eu)) shouldBe "W£♥π"
} }
test("testErrorCases") { test("testErrorCases") {
@ -77,22 +75,6 @@ class TestPetscii: FunSpec({
Petscii.encodePetscii("~", false).expectError { "shouldn't be able to encode tilde" } Petscii.encodePetscii("~", false).expectError { "shouldn't be able to encode tilde" }
Petscii.encodeScreencode("~", true).expectError { "shouldn't be able to encode tilde" } Petscii.encodeScreencode("~", true).expectError { "shouldn't be able to encode tilde" }
Petscii.encodeScreencode("~", false).expectError { "shouldn't be able to encode tilde" } Petscii.encodeScreencode("~", false).expectError { "shouldn't be able to encode tilde" }
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" }
Petscii.petscii2scr(-1, true).expectError { "-1 should error" }
Petscii.petscii2scr(256, true).expectError { "256 should error" }
Petscii.petscii2scr(-1, false).expectError { "-1 should error" }
Petscii.petscii2scr(256, false).expectError { "256 should error" }
} }
test("testSpecialReplacements") { test("testSpecialReplacements") {
@ -104,30 +86,30 @@ class TestPetscii: FunSpec({
Petscii.encodePetscii("~", false).expectError { "shouldn't have translation for tilde" } Petscii.encodePetscii("~", false).expectError { "shouldn't have translation for tilde" }
Petscii.encodePetscii("~", true).expectError { "shouldn't have translation for tilde" } Petscii.encodePetscii("~", true).expectError { "shouldn't have translation for tilde" }
encodeP('^', false) shouldBe 94 encodeP('^', false) shouldBe 94u
encodeP('^', true) shouldBe 94 encodeP('^', true) shouldBe 94u
encodeS('^', false) shouldBe 30 encodeS('^', false) shouldBe 30u
encodeS('^', true) shouldBe 30 encodeS('^', true) shouldBe 30u
encodeP('_', false) shouldBe 228 encodeP('_', false) shouldBe 228u
encodeP('_', true) shouldBe 228 encodeP('_', true) shouldBe 228u
encodeS('_', false) shouldBe 100 encodeS('_', false) shouldBe 100u
encodeS('_', true) shouldBe 100 encodeS('_', true) shouldBe 100u
encodeP('{', false) shouldBe 243 encodeP('{', false) shouldBe 243u
encodeP('{', true) shouldBe 243 encodeP('{', true) shouldBe 243u
encodeS('{', false) shouldBe 115 encodeS('{', false) shouldBe 115u
encodeS('{', true) shouldBe 115 encodeS('{', true) shouldBe 115u
encodeP('}', false) shouldBe 235 encodeP('}', false) shouldBe 235u
encodeP('}', true) shouldBe 235 encodeP('}', true) shouldBe 235u
encodeS('}', false) shouldBe 107 encodeS('}', false) shouldBe 107u
encodeS('}', true) shouldBe 107 encodeS('}', true) shouldBe 107u
encodeP('|', false) shouldBe 221 encodeP('|', false) shouldBe 221u
encodeP('|', true) shouldBe 221 encodeP('|', true) shouldBe 221u
encodeS('|', false) shouldBe 93 encodeS('|', false) shouldBe 93u
encodeS('|', true) shouldBe 93 encodeS('|', true) shouldBe 93u
encodeP('\\', false) shouldBe 205 encodeP('\\', false) shouldBe 205u
encodeP('\\', true) shouldBe 205 encodeP('\\', true) shouldBe 205u
encodeS('\\', false) shouldBe 77 encodeS('\\', false) shouldBe 77u
encodeS('\\', true) shouldBe 77 encodeS('\\', true) shouldBe 77u
} }
test("testBoxDrawingCharsEncoding") { test("testBoxDrawingCharsEncoding") {
@ -135,59 +117,59 @@ class TestPetscii: FunSpec({
fun encodeS(c: Char, lower: Boolean) = Petscii.encodeScreencode(c.toString(), lower).getOrElse { throw it }.single() fun encodeS(c: Char, lower: Boolean) = Petscii.encodeScreencode(c.toString(), lower).getOrElse { throw it }.single()
// pipe char // pipe char
encodeP('|', false) shouldBe 221 encodeP('|', false) shouldBe 221u
encodeP('|', true) shouldBe 221 encodeP('|', true) shouldBe 221u
encodeS('|', false) shouldBe 93 encodeS('|', false) shouldBe 93u
encodeS('|', true) shouldBe 93 encodeS('|', true) shouldBe 93u
// ... same as '│', 0x7D -> BOX DRAWINGS LIGHT VERTICAL // ... same as '│', 0x7D -> BOX DRAWINGS LIGHT VERTICAL
encodeP('│', false) shouldBe 221 encodeP('│', false) shouldBe 221u
encodeP('│', true) shouldBe 221 encodeP('│', true) shouldBe 221u
encodeS('│', false) shouldBe 93 encodeS('│', false) shouldBe 93u
encodeS('│', true) shouldBe 93 encodeS('│', true) shouldBe 93u
// underscore // underscore
encodeP('_', false) shouldBe 228 encodeP('_', false) shouldBe 228u
encodeP('_', true) shouldBe 228 encodeP('_', true) shouldBe 228u
encodeS('_', false) shouldBe 100 encodeS('_', false) shouldBe 100u
encodeS('_', true) shouldBe 100 encodeS('_', true) shouldBe 100u
// ... same as '▁', 0xE4 LOWER ONE EIGHTH BLOCK // ... same as '▁', 0xE4 LOWER ONE EIGHTH BLOCK
encodeP('▁', false) shouldBe 228 encodeP('▁', false) shouldBe 228u
encodeP('▁', true) shouldBe 228 encodeP('▁', true) shouldBe 228u
encodeS('▁', false) shouldBe 100 encodeS('▁', false) shouldBe 100u
encodeS('▁', true) shouldBe 100 encodeS('▁', true) shouldBe 100u
// ─ 0xC0 -> BOX DRAWINGS LIGHT HORIZONTAL // ─ 0xC0 -> BOX DRAWINGS LIGHT HORIZONTAL
encodeP('─', false) shouldBe 192 encodeP('─', false) shouldBe 192u
encodeP('─', true) shouldBe 192 encodeP('─', true) shouldBe 192u
encodeS('─', false) shouldBe 64 encodeS('─', false) shouldBe 64u
encodeS('─', true) shouldBe 64 encodeS('─', true) shouldBe 64u
// │ 0x62 -> BOX DRAWINGS LIGHT VERTICAL // │ 0x62 -> BOX DRAWINGS LIGHT VERTICAL
encodeP('│', false) shouldBe 221 encodeP('│', false) shouldBe 221u
encodeP('│', true) shouldBe 221 encodeP('│', true) shouldBe 221u
encodeS('│', false) shouldBe 93 encodeS('│', false) shouldBe 93u
encodeS('│', true) shouldBe 93 encodeS('│', true) shouldBe 93u
} }
test("testBoxDrawingCharsDecoding") { test("testBoxDrawingCharsDecoding") {
// ─ 0xC0 -> BOX DRAWINGS LIGHT HORIZONTAL // ─ 0xC0 -> BOX DRAWINGS LIGHT HORIZONTAL
Petscii.decodePetscii(listOf(195), false).single() shouldBe '\uf13b' //"BOX DRAWINGS LIGHT HORIZONTAL ONE EIGHTH UP (CUS)" Petscii.decodePetscii(listOf(195u), false).single() shouldBe '\uf13b' //"BOX DRAWINGS LIGHT HORIZONTAL ONE EIGHTH UP (CUS)"
Petscii.decodePetscii(listOf(195), true).single() shouldBe 'C' Petscii.decodePetscii(listOf(195u), true).single() shouldBe 'C'
Petscii.decodePetscii(listOf(192), false).single() shouldBe '─' Petscii.decodePetscii(listOf(192u), false).single() shouldBe '─'
Petscii.decodePetscii(listOf(192), true).single() shouldBe '─' Petscii.decodePetscii(listOf(192u), true).single() shouldBe '─'
Petscii.decodeScreencode(listOf(67), false).single() shouldBe '\uf13b' //"BOX DRAWINGS LIGHT HORIZONTAL ONE EIGHTH UP (CUS)" Petscii.decodeScreencode(listOf(67u), false).single() shouldBe '\uf13b' //"BOX DRAWINGS LIGHT HORIZONTAL ONE EIGHTH UP (CUS)"
Petscii.decodeScreencode(listOf(67), true).single() shouldBe 'C' Petscii.decodeScreencode(listOf(67u), true).single() shouldBe 'C'
Petscii.decodeScreencode(listOf(64), false).single() shouldBe '─' Petscii.decodeScreencode(listOf(64u), false).single() shouldBe '─'
Petscii.decodeScreencode(listOf(64), true).single() shouldBe '─' Petscii.decodeScreencode(listOf(64u), true).single() shouldBe '─'
// │ 0x62 -> BOX DRAWINGS LIGHT VERTICAL // │ 0x62 -> BOX DRAWINGS LIGHT VERTICAL
Petscii.decodePetscii(listOf(125), false).single() shouldBe '│' Petscii.decodePetscii(listOf(125u), false).single() shouldBe '│'
Petscii.decodePetscii(listOf(125), true).single() shouldBe '│' Petscii.decodePetscii(listOf(125u), true).single() shouldBe '│'
Petscii.decodePetscii(listOf(221), false).single() shouldBe '│' Petscii.decodePetscii(listOf(221u), false).single() shouldBe '│'
Petscii.decodePetscii(listOf(221), true).single() shouldBe '│' Petscii.decodePetscii(listOf(221u), true).single() shouldBe '│'
Petscii.decodeScreencode(listOf(93), false).single() shouldBe '│' Petscii.decodeScreencode(listOf(93u), false).single() shouldBe '│'
Petscii.decodeScreencode(listOf(93), true).single() shouldBe '│' Petscii.decodeScreencode(listOf(93u), true).single() shouldBe '│'
Petscii.decodeScreencode(listOf(66), false).single() shouldBe '\uf13c' // "BOX DRAWINGS LIGHT VERTICAL ONE EIGHTH LEFT (CUS)" Petscii.decodeScreencode(listOf(66u), false).single() shouldBe '\uf13c' // "BOX DRAWINGS LIGHT VERTICAL ONE EIGHTH LEFT (CUS)"
Petscii.decodeScreencode(listOf(66), true).single() shouldBe 'B' Petscii.decodeScreencode(listOf(66u), true).single() shouldBe 'B'
} }
}) })

View File

@ -23,11 +23,11 @@ class TestAbstractZeropage: FunSpec({
override val machine: IMachineDefinition override val machine: IMachineDefinition
get() = throw NotImplementedError("dummy") get() = throw NotImplementedError("dummy")
override fun encodeString(str: String, altEncoding: Boolean): List<Short> { override fun encodeString(str: String, altEncoding: Boolean): List<UByte> {
throw NotImplementedError("dummy") throw NotImplementedError("dummy")
} }
override fun decodeString(bytes: List<Short>, altEncoding: Boolean): String { override fun decodeString(bytes: List<UByte>, altEncoding: Boolean): String {
throw NotImplementedError("dummy") throw NotImplementedError("dummy")
} }

View File

@ -26,11 +26,11 @@ internal val DummyMemsizer = object : IMemSizer {
} }
internal val DummyStringEncoder = object : IStringEncoding { internal val DummyStringEncoder = object : IStringEncoding {
override fun encodeString(str: String, altEncoding: Boolean): List<Short> { override fun encodeString(str: String, altEncoding: Boolean): List<UByte> {
return emptyList() return emptyList()
} }
override fun decodeString(bytes: List<Short>, altEncoding: Boolean): String { override fun decodeString(bytes: List<UByte>, altEncoding: Boolean): String {
return "" return ""
} }
} }

View File

@ -113,12 +113,8 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid
"not" -> NumericLiteralValue.fromBoolean(constval.number == 0.0, constval.position) "not" -> NumericLiteralValue.fromBoolean(constval.number == 0.0, constval.position)
else -> throw FatalAstException("invalid operator") else -> throw FatalAstException("invalid operator")
} }
return if(converted==null) converted.linkParents(this.parent)
null return converted
else {
converted.linkParents(this.parent)
converted
}
} }
override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent) override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)

View File

@ -1,6 +1,6 @@
package prog8.compilerinterface package prog8.compilerinterface
interface IStringEncoding { interface IStringEncoding {
fun encodeString(str: String, altEncoding: Boolean): List<Short> fun encodeString(str: String, altEncoding: Boolean): List<UByte>
fun decodeString(bytes: List<Short>, altEncoding: Boolean): String fun decodeString(bytes: List<UByte>, altEncoding: Boolean): String
} }

View File

@ -26,19 +26,19 @@ internal val DummyMemsizer = object : IMemSizer {
} }
internal val DummyStringEncoder = object : IStringEncoding { internal val DummyStringEncoder = object : IStringEncoding {
override fun encodeString(str: String, altEncoding: Boolean): List<Short> { override fun encodeString(str: String, altEncoding: Boolean): List<UByte> {
return emptyList() return emptyList()
} }
override fun decodeString(bytes: List<Short>, altEncoding: Boolean): String { override fun decodeString(bytes: List<UByte>, altEncoding: Boolean): String {
return "" return ""
} }
} }
internal val AsciiStringEncoder = object : IStringEncoding { internal val AsciiStringEncoder = object : IStringEncoding {
override fun encodeString(str: String, altEncoding: Boolean): List<Short> = str.map { it.code.toShort() } override fun encodeString(str: String, altEncoding: Boolean): List<UByte> = str.map { it.code.toUByte() }
override fun decodeString(bytes: List<Short>, altEncoding: Boolean): String { override fun decodeString(bytes: List<UByte>, altEncoding: Boolean): String {
return bytes.joinToString() return bytes.joinToString()
} }
} }

View File

@ -3,6 +3,6 @@ package prog8.compilerinterface
interface ICompilationTarget: IStringEncoding, IMemSizer { interface ICompilationTarget: IStringEncoding, IMemSizer {
val name: String val name: String
val machine: IMachineDefinition val machine: IMachineDefinition
override fun encodeString(str: String, altEncoding: Boolean): List<Short> override fun encodeString(str: String, altEncoding: Boolean): List<UByte>
override fun decodeString(bytes: List<Short>, altEncoding: Boolean): String override fun decodeString(bytes: List<UByte>, altEncoding: Boolean): String
} }

View File

@ -4,5 +4,50 @@ main {
sub start() { sub start() {
ubyte xx = 1
ubyte yy = 2
byte b1
byte b2=10
; result should be: 29 42 40 87 75 35
xx=6
yy=8
yy = (xx+5)+(yy+10)
txt.print_ub(yy) ; 29
txt.nl()
xx=6
yy=8
yy = (xx*3)+(yy*3)
txt.print_ub(yy) ; 42
txt.nl()
b1=13
b2=5
b2 = (b1*5)-(b2*5)
txt.print_b(b2) ; 40
txt.nl()
b1=100
b2=8
b2 = (b1+5)-(b2+10)
txt.print_b(b2) ; 87
txt.nl()
b1=50
b2=40
b2 = (b1-5)+(b2-10)
txt.print_b(b2) ; 75
txt.nl()
b1=50
b2=20
b2 = (b1-5)-(b2-10)
txt.print_b(b2) ; 35
txt.nl()
repeat {
}
} }
} }