mirror of
https://github.com/irmen/prog8.git
synced 2024-07-28 18:29:40 +00:00
stuff
This commit is contained in:
parent
98e95b5707
commit
870c6ea747
@ -347,7 +347,7 @@ interface IFunctionCall {
|
|||||||
interface INameScope {
|
interface INameScope {
|
||||||
val name: String
|
val name: String
|
||||||
val position: Position
|
val position: Position
|
||||||
var statements: MutableList<IStatement>
|
val statements: MutableList<IStatement>
|
||||||
val parent: Node
|
val parent: Node
|
||||||
|
|
||||||
fun linkParents(parent: Node)
|
fun linkParents(parent: Node)
|
||||||
@ -376,17 +376,16 @@ interface INameScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getLabelOrVariable(name: String): IStatement? {
|
fun getLabelOrVariable(name: String): IStatement? {
|
||||||
|
// TODO this call is relatively slow.... cache it? make statement list non-mutable and update the cache when it is explicitly updated?
|
||||||
for (stmt in statements) {
|
for (stmt in statements) {
|
||||||
if (stmt is Label && stmt.name==name) return stmt
|
|
||||||
if (stmt is VarDecl && stmt.name==name) return stmt
|
if (stmt is VarDecl && stmt.name==name) return stmt
|
||||||
|
else if (stmt is Label && stmt.name==name) return stmt
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun allLabelsAndVariables(): Map<String, IStatement> {
|
fun allLabelsAndVariables(): Set<String> =
|
||||||
val labelsAndVars = statements.filterIsInstance<Label>() + statements.filterIsInstance<VarDecl>()
|
statements.filterIsInstance<Label>().map { it.name }.toSet() + statements.filterIsInstance<VarDecl>().map { it.name }.toSet()
|
||||||
return labelsAndVars.associate { ((it as? Label)?.name ?: (it as? VarDecl)?.name)!! to it }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun lookup(scopedName: List<String>, statement: Node) : IStatement? {
|
fun lookup(scopedName: List<String>, statement: Node) : IStatement? {
|
||||||
if(scopedName.size>1) {
|
if(scopedName.size>1) {
|
||||||
@ -419,19 +418,6 @@ interface INameScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun debugPrint() {
|
|
||||||
fun printNames(indent: Int, namespace: INameScope) {
|
|
||||||
println(" ".repeat(4*indent) + "${namespace.name} -> ${namespace::class.simpleName} at ${namespace.position}")
|
|
||||||
namespace.allLabelsAndVariables().forEach {
|
|
||||||
println(" ".repeat(4 * (1 + indent)) + "${it.key} -> ${it.value::class.simpleName} at ${it.value.position}")
|
|
||||||
}
|
|
||||||
namespace.statements.filterIsInstance<INameScope>().forEach {
|
|
||||||
printNames(indent+1, it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printNames(0, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isEmpty() = statements.isEmpty()
|
fun isEmpty() = statements.isEmpty()
|
||||||
fun isNotEmpty() = statements.isNotEmpty()
|
fun isNotEmpty() = statements.isNotEmpty()
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
printWarning("for loop body is empty", forLoop.position)
|
printWarning("for loop body is empty", forLoop.position)
|
||||||
|
|
||||||
if(forLoop.iterable is LiteralValue)
|
if(forLoop.iterable is LiteralValue)
|
||||||
checkResult.add(SyntaxError("currently not possible to loop over a literal value directly, use a variable instead", forLoop.position)) // todo loop over literals (by creating a generated variable)
|
checkResult.add(SyntaxError("currently not possible to loop over a literal value directly, define it as a variable instead", forLoop.position)) // todo loop over literals (by creating a generated variable)
|
||||||
|
|
||||||
if(!forLoop.iterable.isIterable(namespace, heap)) {
|
if(!forLoop.iterable.isIterable(namespace, heap)) {
|
||||||
checkResult.add(ExpressionError("can only loop over an iterable type", forLoop.position))
|
checkResult.add(ExpressionError("can only loop over an iterable type", forLoop.position))
|
||||||
@ -330,7 +330,9 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
if(subroutine.asmClobbers.intersect(regCounts.keys).isNotEmpty())
|
if(subroutine.asmClobbers.intersect(regCounts.keys).isNotEmpty())
|
||||||
err("a return register is also in the clobber list")
|
err("a return register is also in the clobber list")
|
||||||
} else {
|
} else {
|
||||||
// TODO: currently, non-asm subroutines can only take numeric arguments
|
// TODO: currently, non-asm subroutines can only take numeric arguments (including floats)
|
||||||
|
// the way string params are treated is almost okay (their address is passed) but the receiving subroutine treats it as an integer rather than referring back to the original string.
|
||||||
|
// the way array params are treated is buggy; it thinks the subroutine needs a byte parameter in place of a byte[] ...
|
||||||
if(!subroutine.parameters.all{it.type in NumericDatatypes}) {
|
if(!subroutine.parameters.all{it.type in NumericDatatypes}) {
|
||||||
err("non-asm subroutine can only take numerical parameters (no str/array types) for now")
|
err("non-asm subroutine can only take numerical parameters (no str/array types) for now")
|
||||||
}
|
}
|
||||||
|
@ -111,12 +111,13 @@ class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check that there are no local variables that redefine the subroutine's parameters
|
// check that there are no local variables that redefine the subroutine's parameters
|
||||||
val definedNames = subroutine.allLabelsAndVariables() // TODO this call is slow
|
val allDefinedNames = subroutine.allLabelsAndVariables()
|
||||||
val paramNames = subroutine.parameters.map { it.name }
|
val paramNames = subroutine.parameters.map { it.name }.toSet()
|
||||||
val definedNamesCorrespondingToParameters = definedNames.filter { it.key in paramNames }
|
val paramsToCheck = paramNames.intersect(allDefinedNames)
|
||||||
for(name in definedNamesCorrespondingToParameters) {
|
for(name in paramsToCheck) {
|
||||||
if(name.value.position != subroutine.position)
|
val thing = subroutine.getLabelOrVariable(name)!!
|
||||||
nameError(name.key, name.value.position, subroutine)
|
if(thing.position != subroutine.position)
|
||||||
|
nameError(name, thing.position, subroutine)
|
||||||
}
|
}
|
||||||
|
|
||||||
// inject subroutine params as local variables (if they're not there yet) (for non-kernel subroutines and non-asm parameters)
|
// inject subroutine params as local variables (if they're not there yet) (for non-kernel subroutines and non-asm parameters)
|
||||||
@ -126,7 +127,7 @@ class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
|
|||||||
if(subroutine.asmAddress==null) {
|
if(subroutine.asmAddress==null) {
|
||||||
if(subroutine.asmParameterRegisters.isEmpty()) {
|
if(subroutine.asmParameterRegisters.isEmpty()) {
|
||||||
subroutine.parameters
|
subroutine.parameters
|
||||||
.filter { !definedNames.containsKey(it.name) }
|
.filter { it.name !in allDefinedNames }
|
||||||
.forEach {
|
.forEach {
|
||||||
val vardecl = VarDecl(VarDeclType.VAR, it.type, null, it.name, null, subroutine.position)
|
val vardecl = VarDecl(VarDeclType.VAR, it.type, null, it.name, null, subroutine.position)
|
||||||
vardecl.linkParents(subroutine)
|
vardecl.linkParents(subroutine)
|
||||||
|
@ -163,7 +163,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
|
|
||||||
override fun process(block: Block): IStatement {
|
override fun process(block: Block): IStatement {
|
||||||
prog.newBlock(block.scopedname, block.name, block.address, block.options())
|
prog.newBlock(block.scopedname, block.name, block.address, block.options())
|
||||||
processVariables(block) // @todo optimize initializations with same value: load the value only once (sort on initalization value, datatype ?)
|
processVariables(block)
|
||||||
prog.label("block."+block.scopedname, false)
|
prog.label("block."+block.scopedname, false)
|
||||||
prog.line(block.position)
|
prog.line(block.position)
|
||||||
translate(block.statements)
|
translate(block.statements)
|
||||||
@ -183,7 +183,10 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
prog.instr(Opcode.START_PROCDEF)
|
prog.instr(Opcode.START_PROCDEF)
|
||||||
prog.line(subroutine.position)
|
prog.line(subroutine.position)
|
||||||
// note: the caller has already written the arguments into the subroutine's parameter variables.
|
// note: the caller has already written the arguments into the subroutine's parameter variables.
|
||||||
translate(subroutine.statements)
|
val (varinits, others) = subroutine.statements.partition { it is VariableInitializationAssignment }
|
||||||
|
val varInits: List<VariableInitializationAssignment> = varinits as List<VariableInitializationAssignment>
|
||||||
|
translateVarInits(varInits)
|
||||||
|
translate(others)
|
||||||
val r= super.process(subroutine)
|
val r= super.process(subroutine)
|
||||||
prog.instr(Opcode.END_PROCDEF)
|
prog.instr(Opcode.END_PROCDEF)
|
||||||
return r
|
return r
|
||||||
@ -197,12 +200,18 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun translateVarInits(varinits: List<VariableInitializationAssignment>) {
|
||||||
|
// sort by datatype and value, so multiple initializations with the same value can be optimized (to load the value just once)
|
||||||
|
val sortedInits = varinits.sortedWith(compareBy({it.value.resultingDatatype(namespace, heap)}, {it.value.constValue(namespace, heap)?.asNumericValue?.toDouble()}))
|
||||||
|
for (vi in sortedInits)
|
||||||
|
translate(vi)
|
||||||
|
}
|
||||||
|
|
||||||
private fun translate(statements: List<IStatement>) {
|
private fun translate(statements: List<IStatement>) {
|
||||||
for (stmt: IStatement in statements) {
|
for (stmt: IStatement in statements) {
|
||||||
generatedLabelSequenceNumber++
|
generatedLabelSequenceNumber++
|
||||||
when (stmt) {
|
when (stmt) {
|
||||||
is Label -> translate(stmt)
|
is Label -> translate(stmt)
|
||||||
is VariableInitializationAssignment -> translate(stmt) // for initializing vars in a scope
|
|
||||||
is Assignment -> translate(stmt) // normal and augmented assignments
|
is Assignment -> translate(stmt) // normal and augmented assignments
|
||||||
is PostIncrDecr -> translate(stmt)
|
is PostIncrDecr -> translate(stmt)
|
||||||
is Jump -> translate(stmt, null)
|
is Jump -> translate(stmt, null)
|
||||||
@ -1409,13 +1418,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: VariableInitializationAssignment) {
|
|
||||||
// this is an assignment to initialize a variable's value in the scope.
|
|
||||||
// the compiler can perhaps optimize this phase.
|
|
||||||
// todo: optimize variable init by keeping track of the block of init values so it can be copied as a whole via memcopy instead of all separate load value instructions
|
|
||||||
translate(stmt as Assignment)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun translate(stmt: Assignment) {
|
private fun translate(stmt: Assignment) {
|
||||||
prog.line(stmt.position)
|
prog.line(stmt.position)
|
||||||
translate(stmt.value)
|
translate(stmt.value)
|
||||||
|
@ -44,7 +44,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
|||||||
optimizeMultipleSequentialLineInstrs()
|
optimizeMultipleSequentialLineInstrs()
|
||||||
optimizeCallReturnIntoJump()
|
optimizeCallReturnIntoJump()
|
||||||
optimizeRestoreXYSaveXYIntoRestoreXY()
|
optimizeRestoreXYSaveXYIntoRestoreXY()
|
||||||
// todo: optimize stackvm code more
|
// todo: add more optimizations to stackvm code
|
||||||
|
|
||||||
optimizeRemoveNops() // must be done as the last step
|
optimizeRemoveNops() // must be done as the last step
|
||||||
optimizeMultipleSequentialLineInstrs() // once more
|
optimizeMultipleSequentialLineInstrs() // once more
|
||||||
@ -396,9 +396,8 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
|||||||
fun writeCode(out: PrintStream, embeddedLabels: Boolean=true) {
|
fun writeCode(out: PrintStream, embeddedLabels: Boolean=true) {
|
||||||
out.println("; stackVM program code for '$name'")
|
out.println("; stackVM program code for '$name'")
|
||||||
out.println("%memory")
|
out.println("%memory")
|
||||||
if(memory.isNotEmpty()) {
|
if(memory.isNotEmpty())
|
||||||
TODO("output initial memory values")
|
TODO("add support for writing/reading initial memory values")
|
||||||
}
|
|
||||||
out.println("%end_memory")
|
out.println("%end_memory")
|
||||||
out.println("%heap")
|
out.println("%heap")
|
||||||
heap.allEntries().forEach {
|
heap.allEntries().forEach {
|
||||||
|
@ -263,6 +263,7 @@ enum class Opcode {
|
|||||||
RRESTORE, // restore all internal registers and status flags
|
RRESTORE, // restore all internal registers and status flags
|
||||||
RRESTOREX, // restore just X (the evaluation stack pointer)
|
RRESTOREX, // restore just X (the evaluation stack pointer)
|
||||||
RRESTOREY, // restore just Y (used in for loops for instance)
|
RRESTOREY, // restore just Y (used in for loops for instance)
|
||||||
|
|
||||||
NOP, // do nothing
|
NOP, // do nothing
|
||||||
BREAKPOINT, // breakpoint
|
BREAKPOINT, // breakpoint
|
||||||
TERMINATE, // end the program
|
TERMINATE, // end the program
|
||||||
|
@ -254,7 +254,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
vardecls2asm(block)
|
vardecls2asm(block)
|
||||||
out("")
|
out("")
|
||||||
|
|
||||||
val instructionPatternWindowSize = 6
|
val instructionPatternWindowSize = 6 // increase once patterns occur longer than this.
|
||||||
var processed = 0
|
var processed = 0
|
||||||
|
|
||||||
if(trace) println("BLOCK: ${block.scopedname} ${block.address ?: ""}")
|
if(trace) println("BLOCK: ${block.scopedname} ${block.address ?: ""}")
|
||||||
@ -3205,7 +3205,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 16 bit addition avoiding excessive stack usage
|
// 16 bit addition avoiding excessive stack usage
|
||||||
// @todo optimize this even more with longer asmpatterns (avoid stack use altogether on most common operations)
|
// @todo optimize 8 and 16 bit adds and subs even more with longer asmpatterns (avoid stack use altogether on most common operations)
|
||||||
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.ADD_UW),
|
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.ADD_UW),
|
||||||
listOf(Opcode.PUSH_VAR_WORD, Opcode.ADD_W)) { segment ->
|
listOf(Opcode.PUSH_VAR_WORD, Opcode.ADD_W)) { segment ->
|
||||||
"""
|
"""
|
||||||
|
@ -25,6 +25,10 @@ const val ESTACK_HI = 0xcf00 // $cf00-$cfff inclusive
|
|||||||
|
|
||||||
class C64Zeropage(options: CompilationOptions) : Zeropage(options) {
|
class C64Zeropage(options: CompilationOptions) : Zeropage(options) {
|
||||||
|
|
||||||
|
|
||||||
|
// @todo: actually USE the zero page when allocating variables at code generation time
|
||||||
|
// (ideally, the variables that are used 'most' / inside long loops are allocated in ZP first)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val SCRATCH_B1 = 0x02
|
const val SCRATCH_B1 = 0x02
|
||||||
const val SCRATCH_REG = 0x03 // temp storage for a register
|
const val SCRATCH_REG = 0x03 // temp storage for a register
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
<module type="PYTHON_MODULE" version="4">
|
<module type="PYTHON_MODULE" version="4">
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$" />
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||||
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.7" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.7" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
|
@ -171,5 +171,4 @@ texinfo_documents = [
|
|||||||
|
|
||||||
# -- Options for to do extension ----------------------------------------------
|
# -- Options for to do extension ----------------------------------------------
|
||||||
|
|
||||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
|
||||||
todo_include_todos = True
|
todo_include_todos = True
|
||||||
|
@ -311,7 +311,7 @@ ubyte_assignment_to_ubytearray:
|
|||||||
string[mubyte2] = ubarr1[mbyte2] ; via evaluation
|
string[mubyte2] = ubarr1[mbyte2] ; via evaluation
|
||||||
string[mubyte2] = ubarr1[mubyte2] ; via evaluation
|
string[mubyte2] = ubarr1[mubyte2] ; via evaluation
|
||||||
string[mubyte2] = string[mubyte2] ; via evaluation
|
string[mubyte2] = string[mubyte2] ; via evaluation
|
||||||
ubarr1[ubarr2[A]] = ubarr2[ubarr1[Y]] ; via evaluation-- todo check generated asm...
|
ubarr1[ubarr2[A]] = ubarr2[ubarr1[Y]] ; via evaluation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -366,7 +366,7 @@ byte_assignment_to_bytearray:
|
|||||||
barr2[mubyte2] = barr1[ub] ; via evaluation
|
barr2[mubyte2] = barr1[ub] ; via evaluation
|
||||||
barr2[mubyte2] = barr1[mbyte2] ; via evaluation
|
barr2[mubyte2] = barr1[mbyte2] ; via evaluation
|
||||||
barr2[mubyte2] = barr1[mubyte2] ; via evaluation
|
barr2[mubyte2] = barr1[mubyte2] ; via evaluation
|
||||||
barr1[ubarr2[A]] = barr2[ubarr1[Y]] ; via evaluation-- todo check generated asm...
|
barr1[ubarr2[A]] = barr2[ubarr1[Y]] ; via evaluation
|
||||||
|
|
||||||
|
|
||||||
byte_assignment_to_membytearray:
|
byte_assignment_to_membytearray:
|
||||||
@ -420,7 +420,7 @@ byte_assignment_to_membytearray:
|
|||||||
mbarr1[mubyte2] = barr1[ub] ; via evaluation
|
mbarr1[mubyte2] = barr1[ub] ; via evaluation
|
||||||
mbarr1[mubyte2] = barr1[mbyte2] ; via evaluation
|
mbarr1[mubyte2] = barr1[mbyte2] ; via evaluation
|
||||||
mbarr1[mubyte2] = barr1[mubyte2] ; via evaluation
|
mbarr1[mubyte2] = barr1[mubyte2] ; via evaluation
|
||||||
mbarr1[ubarr2[A]] = barr2[ubarr1[Y]] ; via evaluation-- todo check generated asm...
|
mbarr1[ubarr2[A]] = barr2[ubarr1[Y]] ; via evaluation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
str question = "How are you?\n"
|
str question = "How are you?\n"
|
||||||
|
|
||||||
; use iteration to write text
|
; use iteration to write text
|
||||||
for ubyte char in question { ; @todo fix iteration
|
for ubyte char in question {
|
||||||
c64.CHROUT(char)
|
c64.CHROUT(char)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,40 +5,71 @@
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
c64scr.print_ub(c64utils.str2ubyte("1"))
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print_ub(c64utils.str2ubyte("12"))
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print_ub(c64utils.str2ubyte("123"))
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print_ub(c64utils.str2ubyte("1234"))
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print_ub(c64utils.str2ubyte("12xyz"))
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
c64scr.print_ub(c64utils.str2byte("1"))
|
ubyte b1=42
|
||||||
c64.CHROUT('\n')
|
ubyte b2=42
|
||||||
c64scr.print_ub(c64utils.str2byte("12"))
|
ubyte b3=99
|
||||||
c64.CHROUT('\n')
|
ubyte b4=42
|
||||||
c64scr.print_ub(c64utils.str2byte("123"))
|
word w1=42
|
||||||
c64.CHROUT('\n')
|
word w2=42
|
||||||
c64scr.print_ub(c64utils.str2byte("1234"))
|
word w3=99
|
||||||
c64.CHROUT('\n')
|
word w4=42
|
||||||
c64scr.print_ub(c64utils.str2ubyte("12xyz"))
|
uword uw1=42
|
||||||
c64.CHROUT('\n')
|
uword uw2=42
|
||||||
c64.CHROUT('\n')
|
uword uw3=99
|
||||||
|
uword uw4=42
|
||||||
|
float f1 = 3.14
|
||||||
|
float f2 = 3.14
|
||||||
|
float f3 = 99.0
|
||||||
|
float f4 = 3.14
|
||||||
|
str string1="hoi"
|
||||||
|
str string2="hoi"
|
||||||
|
str string3="hoi222"
|
||||||
|
str string4="hoi"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
; c64scr.print_ub(c64utils.str2ubyte("1"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_ub(c64utils.str2ubyte("12"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_ub(c64utils.str2ubyte("123"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_ub(c64utils.str2ubyte("1234"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_ub(c64utils.str2ubyte("12xyz"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; c64scr.print_ub(c64utils.str2byte("1"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_ub(c64utils.str2byte("12"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_ub(c64utils.str2byte("123"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_ub(c64utils.str2byte("1234"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_ub(c64utils.str2ubyte("12xyz"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; c64scr.print_b(c64utils.str2byte("-1"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_b(c64utils.str2byte("-12"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_b(c64utils.str2byte("-123"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_b(c64utils.str2byte("-1111"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_b(c64utils.str2byte("-12xyz"))
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sub foo(ubyte param1, ubyte param2) {
|
||||||
|
ubyte local1
|
||||||
|
}
|
||||||
|
|
||||||
c64scr.print_b(c64utils.str2byte("-1"))
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print_b(c64utils.str2byte("-12"))
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print_b(c64utils.str2byte("-123"))
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print_b(c64utils.str2byte("-1234"))
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print_b(c64utils.str2byte("-12xyz"))
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user