refactoring

This commit is contained in:
Irmen de Jong 2020-10-22 23:41:16 +02:00
parent 2ba6c9ccbe
commit ff3f985658
11 changed files with 64 additions and 67 deletions

View File

@ -151,8 +151,7 @@ io_error:
filename[0] = 'r'
filename[1] = ':'
memcopy(newfileptr, &filename+2, flen_new)
ubyte fis_ix = flen_new+2 ; TODO is temp var for array indexing
filename[fis_ix] = '='
filename[flen_new+2] = '='
memcopy(oldfileptr, &filename+3+flen_new, flen_old+1)
c64.SETNAM(3+flen_new+flen_old, filename)
c64.SETLFS(1, drivenumber, 15)

View File

@ -1 +1 @@
4.6
4.7-SNAPSHOT

View File

@ -250,19 +250,19 @@ internal class AstChecker(private val program: Program,
err("parameter '${param.first.name}' should be ubyte")
}
}
for(ret in subroutine.returntypes.withIndex().zip(subroutine.asmReturnvaluesRegisters)) {
if(ret.second.registerOrPair in setOf(RegisterOrPair.A, RegisterOrPair.X, RegisterOrPair.Y)) {
if (ret.first.value != DataType.UBYTE && ret.first.value != DataType.BYTE)
err("return value #${ret.first.index + 1} should be (u)byte")
subroutine.returntypes.zip(subroutine.asmReturnvaluesRegisters).forEachIndexed { index, pair ->
if(pair.second.registerOrPair in setOf(RegisterOrPair.A, RegisterOrPair.X, RegisterOrPair.Y)) {
if (pair.first != DataType.UBYTE && pair.first != DataType.BYTE)
err("return value #${index + 1} should be (u)byte")
}
else if(ret.second.registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
if (ret.first.value != DataType.UWORD && ret.first.value != DataType.WORD
&& ret.first.value != DataType.STR && ret.first.value !in ArrayDatatypes && ret.first.value != DataType.FLOAT)
err("return value #${ret.first.index + 1} should be (u)word/address")
else if(pair.second.registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
if (pair.first != DataType.UWORD && pair.first != DataType.WORD
&& pair.first != DataType.STR && pair.first !in ArrayDatatypes && pair.first != DataType.FLOAT)
err("return value #${index + 1} should be (u)word/address")
}
else if(ret.second.statusflag!=null) {
if (ret.first.value != DataType.UBYTE)
err("return value #${ret.first.index + 1} should be ubyte")
else if(pair.second.statusflag!=null) {
if (pair.first != DataType.UBYTE)
err("return value #${index + 1} should be ubyte")
}
}
@ -984,8 +984,8 @@ internal class AstChecker(private val program: Program,
if(target.regXasResult())
errors.warn("subroutine call return value in X register is discarded and replaced by 0", position)
if(target.isAsmSubroutine) {
for (arg in args.withIndex().zip(target.parameters)) {
val argIDt = arg.first.value.inferType(program)
for (arg in args.zip(target.parameters)) {
val argIDt = arg.first.inferType(program)
if (!argIDt.isKnown)
return
}

View File

@ -279,7 +279,7 @@ internal class StatementReorderer(val program: Program, val errors: ErrorReporte
}
// TODO use a pointer loop instead of individual assignments
return alv.value.withIndex().map { (index, value)->
return alv.value.mapIndexed { index, value ->
val idx = ArrayIndexedExpression(identifier, ArrayIndex(NumericLiteralValue(DataType.UBYTE, index, position), position), position)
Assignment(AssignTarget(null, idx, null, position), value, value.position)
}

View File

@ -116,30 +116,30 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
when(val sub = call.target.targetStatement(scope)) {
is Subroutine -> {
for(arg in sub.parameters.zip(call.args.withIndex())) {
val argItype = arg.second.value.inferType(program)
sub.parameters.zip(call.args).forEachIndexed { index, pair ->
val argItype = pair.second.inferType(program)
if(argItype.isKnown) {
val argtype = argItype.typeOrElse(DataType.STRUCT)
val requiredType = arg.first.type
val requiredType = pair.first.type
if (requiredType != argtype) {
if (argtype isAssignableTo requiredType) {
modifications += IAstModification.ReplaceNode(
call.args[arg.second.index],
TypecastExpression(arg.second.value, requiredType, true, arg.second.value.position),
call.args[index],
TypecastExpression(pair.second, requiredType, true, pair.second.position),
call as Node)
} else if(requiredType == DataType.UWORD && argtype in PassByReferenceDatatypes) {
// we allow STR/ARRAY values in place of UWORD parameters. Take their address instead.
if(arg.second.value is IdentifierReference) {
if(pair.second is IdentifierReference) {
modifications += IAstModification.ReplaceNode(
call.args[arg.second.index],
AddressOf(arg.second.value as IdentifierReference, arg.second.value.position),
call.args[index],
AddressOf(pair.second as IdentifierReference, pair.second.position),
call as Node)
}
} else if(arg.second.value is NumericLiteralValue) {
val cast = (arg.second.value as NumericLiteralValue).cast(requiredType)
} else if(pair.second is NumericLiteralValue) {
val cast = (pair.second as NumericLiteralValue).cast(requiredType)
if(cast.isValid)
modifications += IAstModification.ReplaceNode(
call.args[arg.second.index],
call.args[index],
cast.valueOrZero(),
call as Node)
}
@ -149,19 +149,19 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke
}
is BuiltinFunctionStatementPlaceholder -> {
val func = BuiltinFunctions.getValue(sub.name)
for (arg in func.parameters.zip(call.args.withIndex())) {
val argItype = arg.second.value.inferType(program)
func.parameters.zip(call.args).forEachIndexed { index, pair ->
val argItype = pair.second.inferType(program)
if (argItype.isKnown) {
val argtype = argItype.typeOrElse(DataType.STRUCT)
if (arg.first.possibleDatatypes.any { argtype == it })
continue
for (possibleType in arg.first.possibleDatatypes) {
if (argtype isAssignableTo possibleType) {
modifications += IAstModification.ReplaceNode(
call.args[arg.second.index],
TypecastExpression(arg.second.value, possibleType, true, arg.second.value.position),
call as Node)
break
if (pair.first.possibleDatatypes.all { argtype != it }) {
for (possibleType in pair.first.possibleDatatypes) {
if (argtype isAssignableTo possibleType) {
modifications += IAstModification.ReplaceNode(
call.args[index],
TypecastExpression(pair.second, possibleType, true, pair.second.position),
call as Node)
break
}
}
}
}

View File

@ -67,12 +67,12 @@ class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {
if(call.args.size != func.parameters.size)
return "invalid number of arguments"
val paramtypes = func.parameters.map { it.possibleDatatypes }
for (x in argtypes.zip(paramtypes).withIndex()) {
val anyCompatible = x.value.second.any { argTypeCompatible(x.value.first, it) }
argtypes.zip(paramtypes).forEachIndexed { index, pair ->
val anyCompatible = pair.second.any { argTypeCompatible(pair.first, it) }
if (!anyCompatible) {
val actual = x.value.first.toString()
val expected = x.value.second.toString()
return "argument ${x.index + 1} type mismatch, was: $actual expected: $expected"
val actual = pair.first.toString()
val expected = pair.second.toString()
return "argument ${index + 1} type mismatch, was: $actual expected: $expected"
}
}
}

View File

@ -252,9 +252,9 @@ open class VarDecl(val type: VarDeclType,
}
fun flattenStructMembers(): MutableList<Statement> {
val result = struct!!.statements.withIndex().map {
val member = it.value as VarDecl
val initvalue = if(value!=null) (value as ArrayLiteralValue).value[it.index] else null
val result = struct!!.statements.mapIndexed { index, statement ->
val member = statement as VarDecl
val initvalue = if(value!=null) (value as ArrayLiteralValue).value[index] else null
VarDecl(
VarDeclType.VAR,
member.datatype,

View File

@ -33,7 +33,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
// via registers
if(sub.parameters.size==1) {
// just a single parameter, no risk of clobbering registers
argumentViaRegister(sub, sub.parameters.withIndex().single(), stmt.args[0])
argumentViaRegister(sub, IndexedValue(0, sub.parameters.single()), stmt.args[0])
} else {
// multiple register arguments, risk of register clobbering.
// evaluate arguments onto the stack, and load the registers from the evaluated values on the stack.

View File

@ -775,8 +775,8 @@ memcopy(from, to, numbytes)
memset(address, numbytes, bytevalue)
Efficiently set a part of memory to the given (u)byte value.
But the most efficient will always be to write a specialized fill routine in assembly yourself!
Note that for clearing the character screen, very fast specialized subroutines are
available in the ``txt`` block (part of the ``textio`` module)
Note that for clearing the screen, very fast specialized subroutines are
available in the ``textio`` and ``graphics`` library modules.
memsetw(address, numwords, wordvalue)
Efficiently set a part of memory to the given (u)word value.

View File

@ -2,14 +2,17 @@
TODO
====
- get rid of all other TODO's in the code ;-)
- implement @stack for asmsub parameters
- make memset(w) and memcopy able to work with >256 bytes
- make memset and memcopy use the ROM routines on the CX16
- calling convention for builtin functions no longer via stack but via statically allocated vars inside the subroutine proc (just as normal subroutines)
- get rid of @stack in asmsub altogether (because all subroutines are no longer using this calling convention anymore)
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)
- see if we can group some errors together for instance the (now single) errors about unidentified symbols
- use VIC banking to move up the graphics bitmap memory location. Don't move it under the ROM though as that would require IRQ disabling and memory bank swapping for every bitmap manipulation
- add some primitives/subroutines/examples for using custom char sets, copying the default charset.
- recursive subroutines? via %option recursive, allocate all params and local vars on estack, don't allow nested subroutines, can begin by first not allowing any local variables just fixing the parameters
- some better handling of recursive subroutines? via %option recursive?: allocate all params and local vars on estack, don't allow nested subroutines, can begin by first not allowing any local variables just fixing the parameters
- get rid of all other TODO's in the code ;-)
More optimizations
^^^^^^^^^^^^^^^^^^

View File

@ -1,26 +1,21 @@
%import textio
%import conv
%import floats
%import diskio
%zeropage basicsafe
main {
sub start() {
uword[] array = [1, 2, 3]
ubyte ii = 0
ubyte ii2 = ii+2
array[ii+1] = array[ii2] ; TODO fix overwriting the single array index autovar
uword xx
for xx in array {
txt.print_uw(xx)
txt.chrout('\n')
}
memcopy($aaaa, $bbbb, 200)
mcp($aaaa, $bbbb, 200)
testX()
}
sub mcp(uword from, uword dest, ubyte length) {
txt.print_uw(from)
txt.print_uw(dest)
txt.print_ub(length)
}
asmsub testX() {
%asm {{
stx _saveX