diff --git a/codeCore/src/prog8/code/core/BuiltinFunctions.kt b/codeCore/src/prog8/code/core/BuiltinFunctions.kt index 2dfab89c8..c972462c4 100644 --- a/codeCore/src/prog8/code/core/BuiltinFunctions.kt +++ b/codeCore/src/prog8/code/core/BuiltinFunctions.kt @@ -81,6 +81,7 @@ val BuiltinFunctions: Map = mapOf( // cmp returns a status in the carry flag, but not a proper return value "cmp" to FSignature(false, listOf(FParam("value1", IntegerDatatypesNoBool), FParam("value2", NumericDatatypesNoBool)), null), "prog8_lib_stringcompare" to FSignature(true, listOf(FParam("str1", arrayOf(DataType.STR)), FParam("str2", arrayOf(DataType.STR))), DataType.BYTE), + "prog8_lib_arraycopy" to FSignature(false, listOf(FParam("source", ArrayDatatypes), FParam("target", ArrayDatatypes)), null), "prog8_lib_square_byte" to FSignature(true, listOf(FParam("value", arrayOf(DataType.BYTE, DataType.UBYTE))), DataType.UBYTE), "prog8_lib_square_word" to FSignature(true, listOf(FParam("value", arrayOf(DataType.WORD, DataType.UWORD))), DataType.UWORD), "abs" to FSignature(true, listOf(FParam("value", NumericDatatypesNoBool)), null), diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index fccd5fb7b..aa05272ba 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -71,12 +71,35 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, "prog8_lib_stringcompare" -> funcStringCompare(fcall, resultRegister) "prog8_lib_square_byte" -> funcSquare(fcall, DataType.UBYTE, resultRegister) "prog8_lib_square_word" -> funcSquare(fcall, DataType.UWORD, resultRegister) + "prog8_lib_arraycopy" -> funcArrayCopy(fcall) else -> throw AssemblyError("missing asmgen for builtin func ${fcall.name}") } return BuiltinFunctions.getValue(fcall.name).returnType } + private fun funcArrayCopy(fcall: PtBuiltinFunctionCall) { + val source = fcall.args[0] as PtIdentifier + val target = fcall.args[1] as PtIdentifier +// outputAddressAndLengthOfArray(source) // address goes in P8ZP_SCRATCH_W1, number of elements in A +// outputAddressAndLengthOfArray(target) // address goes in P8ZP_SCRATCH_W1, number of elements in A + if(source.type in SplitWordArrayTypes && target.type in SplitWordArrayTypes) { + TODO("split to split array copy $source, $target") + } + else if(source.type in SplitWordArrayTypes) { + require(target.type==DataType.ARRAY_UW || target.type==DataType.ARRAY_W) + TODO("split array to normal array copy $source -> $target") + } + else if(target.type in SplitWordArrayTypes) { + require(source.type==DataType.ARRAY_UW || source.type==DataType.ARRAY_W) + TODO("normal array to split array copy $source -> $target") + } + else { + // normal array to array copy + TODO("normal array to array copy $source -> $target") + } + } + private fun funcSquare(fcall: PtBuiltinFunctionCall, resultType: DataType, resultRegister: RegisterOrPair?) { // square of word value is faster with dedicated routine, square of byte just use the regular multiplication routine. when (resultType) { diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index 6dd8167d8..3c9da1e0f 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -48,10 +48,34 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe "prog8_lib_stringcompare" -> funcStringCompare(call) "prog8_lib_square_byte" -> funcSquare(call, IRDataType.BYTE) "prog8_lib_square_word" -> funcSquare(call, IRDataType.WORD) + "prog8_lib_arraycopy" -> funcArrayCopy(call) else -> throw AssemblyError("missing builtinfunc for ${call.name}") } } + private fun funcArrayCopy(call: PtBuiltinFunctionCall): ExpressionCodeResult { + val source = call.args[0] as PtIdentifier + val target = call.args[1] as PtIdentifier + val sourceLength = codeGen.symbolTable.getLength(source.name) + val targetLength = codeGen.symbolTable.getLength(target.name) + require(sourceLength==targetLength) + if(source.type in SplitWordArrayTypes && target.type in SplitWordArrayTypes) { + TODO("split to split array copy $source, $target") + } + else if(source.type in SplitWordArrayTypes) { + require(target.type==DataType.ARRAY_UW || target.type==DataType.ARRAY_W) + TODO("split array to normal array copy $source -> $target") + } + else if(target.type in SplitWordArrayTypes) { + require(source.type==DataType.ARRAY_UW || source.type==DataType.ARRAY_W) + TODO("normal array to split array copy $source -> $target") + } + else { + // normal array to array copy + TODO("normal array to array copy $source -> $target") + } + } + private fun funcSquare(call: PtBuiltinFunctionCall, resultType: IRDataType): ExpressionCodeResult { val result = mutableListOf() val valueTr = exprGen.translateExpression(call.args[0]) diff --git a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt index 818dc1a3f..d75a12b0f 100644 --- a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt +++ b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt @@ -26,6 +26,22 @@ internal class CodeDesugarer(val program: Program, private val errors: IErrorRep // - pointer[word] replaced by @(pointer+word) // - @(&var) and @(&var+1) replaced by lsb(var) and msb(var) if var is a word // - flatten chained assignments + // - replace array assignments by a call to the builtin function that does this: prog8_lib_arraycopy + + override fun after(assignment: Assignment, parent: Node): Iterable { + val targetArray = assignment.target.identifier?.targetVarDecl(program) + val sourceArray = (assignment.value as? IdentifierReference)?.targetVarDecl(program) + if(targetArray?.isArray==true && sourceArray?.isArray==true) { + val copy = FunctionCallStatement( + IdentifierReference(listOf("prog8_lib_arraycopy"), assignment.position), + mutableListOf( + IdentifierReference(listOf(sourceArray.name), assignment.position), + IdentifierReference(listOf(targetArray.name), assignment.position) + ), true, assignment.position) + return listOf(IAstModification.ReplaceNode(assignment, copy, parent)) + } + return noModifications + } override fun before(breakStmt: Break, parent: Node): Iterable { fun jumpAfter(stmt: Statement): Iterable { diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index 5faa5261a..4e870efb5 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -1,7 +1,9 @@ package prog8.compiler.astprocessing import prog8.ast.* -import prog8.ast.expressions.* +import prog8.ast.expressions.ArrayLiteral +import prog8.ast.expressions.BinaryExpression +import prog8.ast.expressions.IdentifierReference import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification @@ -258,27 +260,7 @@ internal class StatementReorderer( errors.err("element size mismatch", assign.position) } } - - if(!errors.noErrors()) - return noModifications - - if(sourceVar.splitArray && targetVar.splitArray) - TODO("copy split to split array") - if(sourceVar.splitArray) - TODO("copy from split source array to normal") - if(targetVar.splitArray) - TODO("copy from normal to split source array") - - val numelements = targetVar.arraysize!!.constIndex()!! - val eltsize = program.memsizer.memorySize(ArrayToElementTypes.getValue(sourceVar.datatype)) - val memcopy = FunctionCallStatement(IdentifierReference(listOf("sys", "memcopy"), assign.position), - mutableListOf( - AddressOf(sourceIdent, null, assign.position), - AddressOf(identifier, null, assign.position), - NumericLiteral.optimalInteger(numelements*eltsize, assign.position) - ), false, assign.position - ) - return listOf(IAstModification.ReplaceNode(assign, memcopy, assign.parent)) + return noModifications } private fun copyStringValue(assign: Assignment): List { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index b5406ab2b..eaa5453f0 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,7 +1,9 @@ TODO ==== -fix TODO's to assign from and to split arrays (StatementReorderer) -- cannot use simple single memcopy here (6502 + IR) +fix bug: txt.setchr(x, y, @(bytes+$1000)) bytes++ doesn't fill the whole screen only the first 256 bytes or something + +fix TODO's to assign from and to split arrays (BuiltinFuncGen + BuiltinFunctionAsmGen) -- cannot use simple single memcopy here (6502 + IR) assembler, imageviewer is bigger than before (since commit "added string.lstripped() and string.ltrimmed()" ) (after merge in boolean): move all "OperatorXinplace" from expressionGen to AssignmentGen, see if we can get rid of the Result return type.