diff --git a/compiler/src/prog8/ast/base/Base.kt b/compiler/src/prog8/ast/base/Base.kt index db89bf278..564c39015 100644 --- a/compiler/src/prog8/ast/base/Base.kt +++ b/compiler/src/prog8/ast/base/Base.kt @@ -31,7 +31,7 @@ enum class DataType { WORD -> targetType in setOf(WORD, FLOAT) FLOAT -> targetType == FLOAT STR -> targetType == STR || targetType == UWORD - in ArrayDatatypes -> targetType == this + in ArrayDatatypes -> targetType == this || targetType == UWORD else -> false } diff --git a/compiler/src/prog8/ast/expressions/InferredTypes.kt b/compiler/src/prog8/ast/expressions/InferredTypes.kt index 90c7ce034..196ddb741 100644 --- a/compiler/src/prog8/ast/expressions/InferredTypes.kt +++ b/compiler/src/prog8/ast/expressions/InferredTypes.kt @@ -35,6 +35,10 @@ object InferredTypes { } override fun hashCode(): Int = Objects.hash(isVoid, datatype) + + infix fun isAssignableTo(targetDt: InferredType): Boolean { + return isKnown && targetDt.isKnown && (datatype!! isAssignableTo targetDt.datatype!!) + } } private val unknownInstance = InferredType.unknown() diff --git a/compiler/src/prog8/ast/processing/AstChecker.kt b/compiler/src/prog8/ast/processing/AstChecker.kt index de5e40557..744b7f392 100644 --- a/compiler/src/prog8/ast/processing/AstChecker.kt +++ b/compiler/src/prog8/ast/processing/AstChecker.kt @@ -380,7 +380,7 @@ internal class AstChecker(private val program: Program, val targetDt = assignment.target.inferType(program, assignment) val valueDt = assignment.value.inferType(program) - if(valueDt.isKnown && valueDt != targetDt) { + if(valueDt.isKnown && !(valueDt isAssignableTo targetDt)) { if(targetDt.typeOrElse(DataType.STRUCT) in IterableDatatypes) errors.err("cannot assign value to string or array", assignment.value.position) else @@ -1350,9 +1350,7 @@ internal class AstChecker(private val program: Program, else if(sourceDatatype== DataType.FLOAT && targetDatatype in IntegerDatatypes) errors.err("cannot assign float to ${targetDatatype.name.toLowerCase()}; possible loss of precision. Suggestion: round the value or revert to integer arithmetic", position) else { - if(targetDatatype==DataType.UWORD && sourceDatatype in PassByReferenceDatatypes) - errors.err("cannot assign ${sourceDatatype.name.toLowerCase()} to ${targetDatatype.name.toLowerCase()}, perhaps forgot '&' ?", position) - else + if(targetDatatype!=DataType.UWORD && sourceDatatype !in PassByReferenceDatatypes) errors.err("cannot assign ${sourceDatatype.name.toLowerCase()} to ${targetDatatype.name.toLowerCase()}", position) } diff --git a/compiler/src/prog8/ast/processing/TypecastsAdder.kt b/compiler/src/prog8/ast/processing/TypecastsAdder.kt index 052a2555b..a74199eb8 100644 --- a/compiler/src/prog8/ast/processing/TypecastsAdder.kt +++ b/compiler/src/prog8/ast/processing/TypecastsAdder.kt @@ -66,6 +66,9 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke val valuetype = valueItype.typeOrElse(DataType.STRUCT) if (valuetype != targettype) { if (valuetype isAssignableTo targettype) { + if(valuetype in IterableDatatypes && targettype==DataType.UWORD) + // special case, don't typecast STR/arrays to UWORD, we support those assignments "directly" + return noModifications return listOf(IAstModification.ReplaceNode( assignment.value, TypecastExpression(assignment.value, targettype, true, assignment.value.position), diff --git a/compiler/src/prog8/ast/statements/AstStatements.kt b/compiler/src/prog8/ast/statements/AstStatements.kt index dbd40694e..16562df77 100644 --- a/compiler/src/prog8/ast/statements/AstStatements.kt +++ b/compiler/src/prog8/ast/statements/AstStatements.kt @@ -697,10 +697,9 @@ class Subroutine(override val name: String, private fun determineReturnRegisters(returntypes: List): List { // for non-asm subroutines, determine the return registers based on the type of the return value return when(returntypes.singleOrNull()) { - in NumericDatatypes -> listOf(RegisterOrStatusflag(null, null, true)) // TODO for now, all return values via the stack -// in ByteDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.A, null, false)) -// in WordDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, false)) -// DataType.FLOAT -> listOf(RegisterOrStatusflag(null, null, true)) // TODO floats eventually via pointer in AY as well + in ByteDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.A, null, false)) + in WordDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, false)) + DataType.FLOAT -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, false)) null -> emptyList() else -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, false)) } diff --git a/compiler/src/prog8/compiler/Main.kt b/compiler/src/prog8/compiler/Main.kt index c96fe45a3..9654708ca 100644 --- a/compiler/src/prog8/compiler/Main.kt +++ b/compiler/src/prog8/compiler/Main.kt @@ -58,7 +58,7 @@ fun compileProgram(filepath: Path, optimizeAst(programAst, errors) postprocessAst(programAst, errors, compilationOptions) - // printAst(programAst) + printAst(programAst) // TODO if(writeAssembly) programName = writeAssembly(programAst, errors, outputDir, optimize, compilationOptions) @@ -223,7 +223,7 @@ private fun writeAssembly(programAst: Program, errors: ErrorReporter, outputDir: programAst.processAstBeforeAsmGeneration(errors) errors.handle() - // printAst(programAst) + printAst(programAst) // TODO CompilationTarget.instance.machine.initializeZeropage(compilerOptions) val assembly = CompilationTarget.instance.asmGenerator( diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index 29f93c146..9c3749939 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -743,8 +743,8 @@ internal class AsmGen(private val program: Program, internal fun translateExpression(indexer: ArrayIndex) = expressionsAsmGen.translateExpression(indexer) - internal fun translateFunctioncallExpression(functionCall: FunctionCall, signature: FSignature) = - builtinFunctionsAsmGen.translateFunctioncallExpression(functionCall, signature) + internal fun translateBuiltinFunctionCallExpression(functionCall: FunctionCall, signature: FSignature, resultToStack: Boolean) = + builtinFunctionsAsmGen.translateFunctioncallExpression(functionCall, signature, resultToStack) internal fun translateFunctionCall(functionCall: FunctionCall, preserveStatusRegisterAfterCall: Boolean) = functioncallAsmGen.translateFunctionCall(functionCall, preserveStatusRegisterAfterCall) @@ -1164,15 +1164,20 @@ $counterVar .byte 0""") else -> throw AssemblyError("normal subroutines can't return value in status register directly") } - if (returnType in NumericDatatypes) { - val src = AsmAssignSource.fromAstSource(returnvalue, program, this) - assignmentAsmGen.translateNormalAssignment(AsmAssignment(src, returnValueTarget, false, ret.position)) - } - else { - // all else take its address and assign that also to AY register pair - val addrofValue = AddressOf(returnvalue as IdentifierReference, returnvalue.position) - val src = AsmAssignSource.fromAstSource(addrofValue, program, this) - assignmentAsmGen.translateNormalAssignment(AsmAssignment(src, returnValueTarget, false, ret.position)) + when (returnType) { + in IntegerDatatypes -> { + val src = AsmAssignSource.fromAstSource(returnvalue, program, this) + assignmentAsmGen.translateNormalAssignment(AsmAssignment(src, returnValueTarget, false, ret.position)) + } + DataType.FLOAT -> { + TODO("must return the float's address in AY") + } + else -> { + // all else take its address and assign that also to AY register pair + val addrofValue = AddressOf(returnvalue as IdentifierReference, returnvalue.position) + val src = AsmAssignSource.fromAstSource(addrofValue, program, this) + assignmentAsmGen.translateNormalAssignment(AsmAssignment(src, returnValueTarget, false, ret.position)) + } } } out(" rts") diff --git a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt index 14063213c..3a8f3ca78 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt @@ -17,37 +17,36 @@ import prog8.functions.FSignature internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen) { - internal fun translateFunctioncallExpression(fcall: FunctionCall, func: FSignature) { - translateFunctioncall(fcall, func, false) + internal fun translateFunctioncallExpression(fcall: FunctionCall, func: FSignature, resultToStack: Boolean) { + translateFunctioncall(fcall, func, discardResult = false, resultToStack = resultToStack) } internal fun translateFunctioncallStatement(fcall: FunctionCallStatement, func: FSignature) { - translateFunctioncall(fcall, func, true) + translateFunctioncall(fcall, func, discardResult = true, resultToStack = false) } - private fun translateFunctioncall(fcall: IFunctionCall, func: FSignature, discardResult: Boolean) { + private fun translateFunctioncall(fcall: IFunctionCall, func: FSignature, discardResult: Boolean, resultToStack: Boolean) { val functionName = fcall.target.nameInSource.last() - if (discardResult) { - if (func.pure) - return // can just ignore the whole function call altogether - else if (func.returntype != null) - throw AssemblyError("discarding result of non-pure function $fcall") - } + if (discardResult && func.pure) + return // can just ignore the whole function call altogether + + if(discardResult && resultToStack) + throw AssemblyError("cannot both discard the result AND put it onto stack") when (functionName) { - "msb" -> funcMsb(fcall) - "lsb" -> funcLsb(fcall) - "mkword" -> funcMkword(fcall, func) - "abs" -> funcAbs(fcall, func) + "msb" -> funcMsb(fcall, resultToStack) + "lsb" -> funcLsb(fcall, resultToStack) + "mkword" -> funcMkword(fcall, func) // TODO resultToStack + "abs" -> funcAbs(fcall, func) // TODO resultToStack "swap" -> funcSwap(fcall) - "strlen" -> funcStrlen(fcall) - "min", "max", "sum" -> funcMinMaxSum(fcall, functionName) - "any", "all" -> funcAnyAll(fcall, functionName) - "sgn" -> funcSgn(fcall, func) + "strlen" -> funcStrlen(fcall) // TODO resultToStack + "min", "max", "sum" -> funcMinMaxSum(fcall, functionName) // TODO resultToStack + "any", "all" -> funcAnyAll(fcall, functionName) // TODO resultToStack + "sgn" -> funcSgn(fcall, func) // TODO resultToStack "sin", "cos", "tan", "atan", "ln", "log2", "sqrt", "rad", "deg", "round", "floor", "ceil", - "rdnf" -> funcVariousFloatFuncs(fcall, func, functionName) + "rdnf" -> funcVariousFloatFuncs(fcall, func, functionName) // TODO resultToStack "rol" -> funcRol(fcall) "rol2" -> funcRol2(fcall) "ror" -> funcRor(fcall) @@ -69,7 +68,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val "set_irqd" -> asmgen.out(" sei") else -> { translateFunctionArguments(fcall.args, func) - asmgen.out(" jsr prog8_lib.func_$functionName") + asmgen.out(" jsr prog8_lib.func_$functionName") // TODO resultToStack } } } @@ -777,7 +776,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen.out(" inx | lda P8ESTACK_LO,x | sta P8ESTACK_HI+1,x") } - private fun funcMsb(fcall: IFunctionCall) { + private fun funcMsb(fcall: IFunctionCall, resultToStack: Boolean) { val arg = fcall.args.single() if (arg.inferType(program).typeOrElse(DataType.STRUCT) !in WordDatatypes) throw AssemblyError("msb required word argument") @@ -785,14 +784,17 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val throw AssemblyError("msb(const) should have been const-folded away") if (arg is IdentifierReference) { val sourceName = asmgen.asmVariableName(arg) - asmgen.out(" lda $sourceName+1 | sta P8ESTACK_LO,x | dex") + asmgen.out(" lda $sourceName+1") + if(resultToStack) + asmgen.out(" sta P8ESTACK_LO,x | dex") } else { - asmgen.translateExpression(arg) - asmgen.out(" lda P8ESTACK_HI+1,x | sta P8ESTACK_LO+1,x") + TODO("msb from non-identifier expression $arg") +// asmgen.translateExpression(arg) +// asmgen.out(" lda P8ESTACK_HI+1,x | sta P8ESTACK_LO+1,x") } } - private fun funcLsb(fcall: IFunctionCall) { + private fun funcLsb(fcall: IFunctionCall, resultToStack: Boolean) { val arg = fcall.args.single() if (arg.inferType(program).typeOrElse(DataType.STRUCT) !in WordDatatypes) throw AssemblyError("lsb required word argument") @@ -800,9 +802,12 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val throw AssemblyError("lsb(const) should have been const-folded away") if (arg is IdentifierReference) { val sourceName = asmgen.asmVariableName(arg) - asmgen.out(" lda $sourceName | sta P8ESTACK_LO,x | dex") + asmgen.out(" lda $sourceName") + if(resultToStack) + asmgen.out(" sta P8ESTACK_LO,x | dex") } else { - asmgen.translateExpression(arg) + TODO("lsb from non-identifier expression $arg") +// asmgen.translateExpression(arg) // just ignore any high-byte } } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt index 8e28aaadb..5897eaa4a 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt @@ -4,6 +4,8 @@ import prog8.ast.Program import prog8.ast.base.* import prog8.ast.expressions.* import prog8.ast.statements.ArrayIndex +import prog8.ast.statements.BuiltinFunctionStatementPlaceholder +import prog8.ast.statements.Subroutine import prog8.compiler.AssemblyError import prog8.compiler.target.CompilationTarget import prog8.compiler.target.CpuType @@ -1041,12 +1043,14 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge } private fun translateFunctionCallResultOntoStack(expression: FunctionCall) { - val functionName = expression.target.nameInSource.last() - val builtinFunc = BuiltinFunctions[functionName] - if (builtinFunc != null) { - asmgen.translateFunctioncallExpression(expression, builtinFunc) + // only for use in nested expression evaluation + + val sub = expression.target.targetStatement(program.namespace) + if(sub is BuiltinFunctionStatementPlaceholder) { + val builtinFunc = BuiltinFunctions.getValue(sub.name) + asmgen.translateBuiltinFunctionCallExpression(expression, builtinFunc, true) } else { - val sub = expression.target.targetSubroutine(program.namespace)!! + sub as Subroutine val preserveStatusRegisterAfterCall = sub.asmReturnvaluesRegisters.any {it.statusflag!=null} asmgen.translateFunctionCall(expression, preserveStatusRegisterAfterCall) val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt index 59873de9d..9563624d0 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt @@ -3,10 +3,7 @@ package prog8.compiler.target.c64.codegen.assignment import prog8.ast.Program import prog8.ast.base.* import prog8.ast.expressions.* -import prog8.ast.statements.AssignTarget -import prog8.ast.statements.Assignment -import prog8.ast.statements.DirectMemoryWrite -import prog8.ast.statements.Subroutine +import prog8.ast.statements.* import prog8.compiler.AssemblyError import prog8.compiler.target.c64.codegen.AsmGen @@ -121,33 +118,26 @@ internal class AsmAssignSource(val kind: SourceStorageKind, val dt = value.inferType(program).typeOrElse(DataType.STRUCT) AsmAssignSource(SourceStorageKind.ARRAY, program, asmgen, dt, array = value) } - else -> { - if(value is FunctionCall) { - // functioncall. - val asmSub = value.target.targetStatement(program.namespace) - if(asmSub is Subroutine && asmSub.isAsmSubroutine) { - when (asmSub.asmReturnvaluesRegisters.count { rr -> rr.registerOrPair!=null }) { - 0 -> throw AssemblyError("can't translate zero return values in assignment") - 1 -> { - // assignment generation itself must make sure the status register is correct after the subroutine call, if status register is involved! - val reg = asmSub.asmReturnvaluesRegisters.single { rr->rr.registerOrPair!=null }.registerOrPair!! - val dt = when(reg) { - RegisterOrPair.A, - RegisterOrPair.X, - RegisterOrPair.Y -> DataType.UBYTE - RegisterOrPair.AX, - RegisterOrPair.AY, - RegisterOrPair.XY -> DataType.UWORD - } - return AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, dt, expression = value) - } - else -> throw AssemblyError("can't translate multiple return values in assignment") - } + is FunctionCall -> { + when (val sub = value.target.targetStatement(program.namespace)) { + is Subroutine -> { + val returnType = sub.returntypes.zip(sub.asmReturnvaluesRegisters).firstOrNull { rr -> rr.second.registerOrPair != null }?.first + ?: throw AssemblyError("can't translate zero return values in assignment") + + AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, returnType, expression = value) + } + is BuiltinFunctionStatementPlaceholder -> { + val returnType = value.inferType(program).typeOrElse(DataType.STRUCT) + AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, returnType, expression = value) + } + else -> { + throw AssemblyError("weird call") } } - + } + else -> { val dt = value.inferType(program).typeOrElse(DataType.STRUCT) - return AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, dt, expression = value) + AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, dt, expression = value) } } } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt index 02a975e60..0d2ba9dd8 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -10,6 +10,7 @@ import prog8.compiler.target.CpuType import prog8.compiler.target.c64.codegen.AsmGen import prog8.compiler.target.c64.codegen.ExpressionsAsmGen import prog8.compiler.toHex +import prog8.functions.BuiltinFunctions internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen, private val exprAsmgen: ExpressionsAsmGen) { @@ -124,28 +125,36 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen is DirectMemoryRead -> throw AssemblyError("source kind should have been memory") is TypecastExpression -> assignTypeCastedValue(assign.target, value.type, value.expression, assign) is FunctionCall -> { - if(value.target.targetSubroutine(program.namespace)?.isAsmSubroutine==true) { - // handle asmsub functioncalls specifically, without shoving stuff on the estack - val sub = value.target.targetSubroutine(program.namespace)!! - val preserveStatusRegisterAfterCall = sub.asmReturnvaluesRegisters.any { it.statusflag != null } - asmgen.translateFunctionCall(value, preserveStatusRegisterAfterCall) - when((sub.asmReturnvaluesRegisters.single { it.registerOrPair!=null }).registerOrPair) { - RegisterOrPair.A -> assignRegisterByte(assign.target, CpuRegister.A) - RegisterOrPair.X -> assignRegisterByte(assign.target, CpuRegister.X) - RegisterOrPair.Y -> assignRegisterByte(assign.target, CpuRegister.Y) - RegisterOrPair.AX -> assignRegisterpairWord(assign.target, RegisterOrPair.AX) - RegisterOrPair.AY -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) - RegisterOrPair.XY -> assignRegisterpairWord(assign.target, RegisterOrPair.XY) - else -> throw AssemblyError("should be just one register byte result value") + when (val sub = value.target.targetStatement(program.namespace)) { + is Subroutine -> { + val preserveStatusRegisterAfterCall = sub.asmReturnvaluesRegisters.any { it.statusflag != null } + asmgen.translateFunctionCall(value, preserveStatusRegisterAfterCall) + when ((sub.asmReturnvaluesRegisters.single { it.registerOrPair != null }).registerOrPair) { + RegisterOrPair.A -> assignRegisterByte(assign.target, CpuRegister.A) + RegisterOrPair.X -> assignRegisterByte(assign.target, CpuRegister.X) + RegisterOrPair.Y -> assignRegisterByte(assign.target, CpuRegister.Y) + RegisterOrPair.AX -> assignRegisterpairWord(assign.target, RegisterOrPair.AX) + RegisterOrPair.AY -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) + RegisterOrPair.XY -> assignRegisterpairWord(assign.target, RegisterOrPair.XY) + else -> throw AssemblyError("should be just one register byte result value") + } + if (preserveStatusRegisterAfterCall) + asmgen.out(" plp\t; restore status flags from call") + } + is BuiltinFunctionStatementPlaceholder -> { + val signature = BuiltinFunctions.getValue(sub.name) + asmgen.translateBuiltinFunctionCallExpression(value, signature, false) + when(signature.returntype) { + in ByteDatatypes -> assignRegisterByte(assign.target, CpuRegister.A) + in WordDatatypes -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) + DataType.FLOAT -> TODO("assign float result from ${sub.name}") + null -> {} + else -> throw AssemblyError("weird result type ${signature.returntype}") + } + } + else -> { + throw AssemblyError("weird func call") } - if(preserveStatusRegisterAfterCall) - asmgen.out(" plp\t; restore status flags from call") - } else { - // regular subroutine, return values are (for now) always done via the stack... TODO optimize this - asmgen.translateExpression(value) - if(assign.target.datatype in WordDatatypes && assign.source.datatype in ByteDatatypes) - asmgen.signExtendStackLsb(assign.source.datatype) - assignStackValue(assign.target) } } else -> { @@ -763,7 +772,14 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } private fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) { - require(target.datatype in WordDatatypes) + require(target.datatype in NumericDatatypes) + if(target.datatype==DataType.FLOAT) { + if (regs == RegisterOrPair.AY) { + asmgen.out(" brk ; TODO FLOAT RETURN VALUE") // TODO + return + } + else throw AssemblyError("float reaturn value should be via AY return pointer") + } when(target.kind) { TargetStorageKind.VARIABLE -> { when(regs) { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 43bc58b79..9eb01103a 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -2,6 +2,7 @@ TODO ==== +- get rid of all the .typeOrElse(STRUCT) 'shortcuts' and replace them with proper error handling - 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) diff --git a/examples/line-circle-txt.p8 b/examples/line-circle-txt.p8 index 2783562d6..b919913ea 100644 --- a/examples/line-circle-txt.p8 +++ b/examples/line-circle-txt.p8 @@ -4,6 +4,8 @@ ; Note: this program is compatible with C64 and CX16. +; TODO the LINES are all wrong... + main { sub start() { diff --git a/examples/test.p8 b/examples/test.p8 index eaf0fd283..ecb138cba 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,13 +6,38 @@ main { sub start() { - ubyte char = c64.CHRIN() - ubyte char2 = chrin() - uword ssss = getstr() - float fl = getfloat() + ubyte char + uword ssss + float fl + ;char = 1+(lsb(ssss) * 2) + ;fl = 2.0*(abs(fl) + 1.0) + + char = lsb(ssss) char++ - char2++ + char = msb(ssss) + char++ + char = c64.CHRIN() + + txt.print_ub(char) + txt.chrout('\n') + + char = chrin() + + txt.print_ub(char) + txt.chrout('\n') + + void getstr() + ssss = getstr() + + txt.print_uwhex(ssss, true) + txt.chrout('\n') + +; fl = getfloat() +; +; floats.print_f(fl) +; txt.chrout('\n') + testX() ;char=strlen(ssss) } @@ -22,12 +47,13 @@ main { } sub getstr() -> str { + @($d020)++ return "foo" } - sub getfloat() -> float { - return 4.56789 - } +; sub getfloat() -> float { +; return 4.56789 +; } sub mcp(uword from, uword dest, ubyte length) { txt.print_uw(from)