mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
strlen and strings with zeros in them should terminate at the zero
This commit is contained in:
parent
f49eefad6f
commit
060e05c868
@ -3,6 +3,7 @@ package prog8.astvm
|
||||
import prog8.ast.*
|
||||
import prog8.compiler.RuntimeValue
|
||||
import prog8.compiler.RuntimeValueRange
|
||||
import prog8.compiler.target.c64.Petscii
|
||||
import java.awt.EventQueue
|
||||
|
||||
|
||||
@ -217,9 +218,24 @@ class AstVm(val program: Program) {
|
||||
if(value.type!=DataType.FLOAT)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.STR, DataType.STR_S -> {
|
||||
if(value.type !in ByteDatatypes)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
else -> throw VmExecutionException("strange array type ${array.type}")
|
||||
}
|
||||
array.array!![index.integerValue()] = value.numericValue()
|
||||
if(array.type in ArrayDatatypes)
|
||||
array.array!![index.integerValue()] = value.numericValue()
|
||||
else if(array.type in StringDatatypes) {
|
||||
val index = index.integerValue()
|
||||
val newchr = Petscii.decodePetscii(listOf(value.numericValue().toShort()), true)
|
||||
val newstr = array.str!!.replaceRange(index, index+1, newchr)
|
||||
val ident = stmt.definingScope().lookup(target.arrayindexed.identifier.nameInSource, stmt) as? VarDecl
|
||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
||||
val identScope = ident.definingScope()
|
||||
program.heap.update(array.heapId!!, newstr)
|
||||
runtimeVariables.set(identScope, ident.name, RuntimeValue(array.type, str=newstr, heapId=array.heapId))
|
||||
}
|
||||
}
|
||||
target.register!=null -> {
|
||||
runtimeVariables.set(program.namespace, target.register.name, value)
|
||||
|
@ -14,6 +14,15 @@ class BuiltinFunctions {
|
||||
"rnd" -> RuntimeValue(DataType.UBYTE, rnd.nextInt() and 255)
|
||||
"rndw" -> RuntimeValue(DataType.UWORD, rnd.nextInt() and 65535)
|
||||
"rndf" -> RuntimeValue(DataType.FLOAT, rnd.nextDouble())
|
||||
"lsb" -> RuntimeValue(DataType.UBYTE, args[0].integerValue() and 255)
|
||||
"msb" -> RuntimeValue(DataType.UBYTE, (args[0].integerValue() ushr 8) and 255)
|
||||
"strlen" -> {
|
||||
val zeroIndex = args[0].str!!.indexOf(0.toChar())
|
||||
if(zeroIndex>=0)
|
||||
RuntimeValue(DataType.UBYTE, zeroIndex)
|
||||
else
|
||||
RuntimeValue(DataType.UBYTE, args[0].str!!.length)
|
||||
}
|
||||
"memset" -> {
|
||||
val target = args[0].array!!
|
||||
val amount = args[1].integerValue()
|
||||
|
@ -61,7 +61,8 @@ class BitmapScreenPanel : KeyListener, JPanel() {
|
||||
g2d.drawLine(x1, y1, x2, y2)
|
||||
}
|
||||
fun printText(text: String, color: Int, lowercase: Boolean) {
|
||||
val lines = text.split('\n')
|
||||
val t2 = text.substringBefore(0.toChar())
|
||||
val lines = t2.split('\n')
|
||||
for(line in lines.withIndex()) {
|
||||
printTextSingleLine(line.value, color, lowercase)
|
||||
if(line.index<lines.size-1) {
|
||||
@ -124,6 +125,8 @@ class BitmapScreenPanel : KeyListener, JPanel() {
|
||||
g2d.clearRect(8*clearx, 8*y, 8, 8)
|
||||
}
|
||||
for(sc in Petscii.encodeScreencode(text, lowercase)) {
|
||||
if(sc==0.toShort())
|
||||
break
|
||||
setChar(xx++, y, sc)
|
||||
}
|
||||
}
|
||||
|
@ -9,12 +9,12 @@ class VariablesCreator(private val runtimeVariables: RuntimeVariables, private v
|
||||
override fun process(program: Program) {
|
||||
// define the three registers as global variables
|
||||
runtimeVariables.define(program.namespace, Register.A.name, RuntimeValue(DataType.UBYTE, 0))
|
||||
runtimeVariables.define(program.namespace, Register.X.name, RuntimeValue(DataType.UBYTE, 0))
|
||||
runtimeVariables.define(program.namespace, Register.X.name, RuntimeValue(DataType.UBYTE, 255))
|
||||
runtimeVariables.define(program.namespace, Register.Y.name, RuntimeValue(DataType.UBYTE, 0))
|
||||
|
||||
val globalpos = Position("<<global>>", 0, 0, 0)
|
||||
val vdA = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, false, Register.A.name, LiteralValue.optimalInteger(0, globalpos), globalpos)
|
||||
val vdX = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, false, Register.X.name, LiteralValue.optimalInteger(0, globalpos), globalpos)
|
||||
val vdX = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, false, Register.X.name, LiteralValue.optimalInteger(255, globalpos), globalpos)
|
||||
val vdY = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, false, Register.Y.name, LiteralValue.optimalInteger(0, globalpos), globalpos)
|
||||
vdA.linkParents(program.namespace)
|
||||
vdX.linkParents(program.namespace)
|
||||
@ -27,25 +27,33 @@ class VariablesCreator(private val runtimeVariables: RuntimeVariables, private v
|
||||
}
|
||||
|
||||
override fun process(decl: VarDecl): IStatement {
|
||||
if(decl.type==VarDeclType.VAR) {
|
||||
val value = when (decl.datatype) {
|
||||
in NumericDatatypes -> {
|
||||
if(decl.value !is LiteralValue) {
|
||||
TODO("evaluate vardecl expression $decl")
|
||||
//RuntimeValue(decl.datatype, num = evaluate(decl.value!!, program, runtimeVariables, executeSubroutine).numericValue())
|
||||
} else {
|
||||
when(decl.type) {
|
||||
VarDeclType.VAR -> {
|
||||
val value = when (decl.datatype) {
|
||||
in NumericDatatypes -> {
|
||||
if(decl.value !is LiteralValue) {
|
||||
TODO("evaluate vardecl expression $decl")
|
||||
//RuntimeValue(decl.datatype, num = evaluate(decl.value!!, program, runtimeVariables, executeSubroutine).numericValue())
|
||||
} else {
|
||||
RuntimeValue.from(decl.value as LiteralValue, heap)
|
||||
}
|
||||
}
|
||||
in StringDatatypes -> {
|
||||
RuntimeValue.from(decl.value as LiteralValue, heap)
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
RuntimeValue.from(decl.value as LiteralValue, heap)
|
||||
}
|
||||
else -> throw VmExecutionException("weird type ${decl.datatype}")
|
||||
}
|
||||
in StringDatatypes -> {
|
||||
RuntimeValue.from(decl.value as LiteralValue, heap)
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
RuntimeValue.from(decl.value as LiteralValue, heap)
|
||||
}
|
||||
else -> throw VmExecutionException("weird type ${decl.datatype}")
|
||||
runtimeVariables.define(decl.definingScope(), decl.name, value)
|
||||
}
|
||||
VarDeclType.MEMORY -> {
|
||||
// TODO register memory mapped vars?
|
||||
}
|
||||
VarDeclType.CONST -> {
|
||||
// consts should have been const-folded away
|
||||
}
|
||||
runtimeVariables.define(decl.definingScope(), decl.name, value)
|
||||
}
|
||||
return super.process(decl)
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ class Petscii {
|
||||
// character tables used from https://github.com/dj51d/cbmcodecs
|
||||
|
||||
private val decodingPetsciiLowercase = arrayOf(
|
||||
'\ufffe', // 0x00 -> UNDEFINED
|
||||
'\u0000', // 0x00 -> \u0000
|
||||
'\ufffe', // 0x01 -> UNDEFINED
|
||||
'\ufffe', // 0x02 -> UNDEFINED
|
||||
'\ufffe', // 0x03 -> UNDEFINED
|
||||
@ -268,7 +268,7 @@ class Petscii {
|
||||
)
|
||||
|
||||
private val decodingPetsciiUppercase = arrayOf(
|
||||
'\ufffe', // 0x00 -> UNDEFINED
|
||||
'\u0000', // 0x00 -> \u0000
|
||||
'\ufffe', // 0x01 -> UNDEFINED
|
||||
'\ufffe', // 0x02 -> UNDEFINED
|
||||
'\ufffe', // 0x03 -> UNDEFINED
|
||||
|
@ -268,6 +268,14 @@ class TestZeropage {
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class TestPetscii {
|
||||
|
||||
@Test
|
||||
fun testZero() {
|
||||
assertThat(Petscii.encodePetscii("\u0000", true), equalTo(listOf<Short>(0)))
|
||||
assertThat(Petscii.encodePetscii("\u0000", false), equalTo(listOf<Short>(0)))
|
||||
assertThat(Petscii.decodePetscii(listOf(0), true), equalTo("\u0000"))
|
||||
assertThat(Petscii.decodePetscii(listOf(0), false), equalTo("\u0000"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLowercase() {
|
||||
assertThat(Petscii.encodePetscii("hello WORLD 123 @!£", true), equalTo(
|
||||
|
@ -6,39 +6,20 @@
|
||||
~ main {
|
||||
|
||||
sub start() {
|
||||
c64scr.print_ub(rnd())
|
||||
uword uw = $ab34
|
||||
str name = "irmen de jong"
|
||||
|
||||
c64scr.print_ub(len(name))
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(rnd())
|
||||
c64scr.print_ub(strlen(name))
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(rnd())
|
||||
c64scr.print(name)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_uw(rndw())
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_uw(rndw())
|
||||
c64.CHROUT('\n')
|
||||
c64flt.print_f(rndf())
|
||||
c64.CHROUT('\n')
|
||||
c64flt.print_f(rndf())
|
||||
name[6] = 0
|
||||
c64scr.print_ub(strlen(name))
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print(name)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
A=rnd()
|
||||
c64scr.print_ub(A)
|
||||
c64.CHROUT('\n')
|
||||
A=rnd()
|
||||
c64scr.print_ub(A)
|
||||
c64.CHROUT('\n')
|
||||
A=rnd()
|
||||
c64scr.print_ub(A)
|
||||
c64.CHROUT('\n')
|
||||
A=rnd()
|
||||
c64scr.print_ub(A)
|
||||
c64.CHROUT('\n')
|
||||
A=rnd()
|
||||
c64scr.print_ub(A)
|
||||
c64.CHROUT('\n')
|
||||
A=rnd()
|
||||
c64scr.print_ub(A)
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user