mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 08:29:25 +00:00
refactoring
This commit is contained in:
parent
2ba6c9ccbe
commit
ff3f985658
@ -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)
|
||||
|
@ -1 +1 @@
|
||||
4.6
|
||||
4.7-SNAPSHOT
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user