mirror of
https://github.com/irmen/prog8.git
synced 2024-10-19 07:23:56 +00:00
avoid adding unneeded variable initalization assignments. Improved removal of useless double assignments.
This commit is contained in:
parent
bda1c1c1eb
commit
95e9e1b550
@ -240,7 +240,7 @@ class Program(val name: String, val modules: MutableList<Module>): Node {
|
|||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
modules.forEach {
|
modules.forEach {
|
||||||
it.linkParents(this)
|
it.linkParents(namespace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,8 +327,6 @@ class GlobalNamespace(val modules: List<Module>): Node, INameScope {
|
|||||||
if(symbolFromInnerScope!=null)
|
if(symbolFromInnerScope!=null)
|
||||||
return symbolFromInnerScope
|
return symbolFromInnerScope
|
||||||
}
|
}
|
||||||
val p1 = localContext.parent
|
|
||||||
val p2 = localContext.parent.parent
|
|
||||||
|
|
||||||
// lookup something from the module.
|
// lookup something from the module.
|
||||||
return when (val stmt = localContext.definingModule().lookup(scopedName, localContext)) {
|
return when (val stmt = localContext.definingModule().lookup(scopedName, localContext)) {
|
||||||
|
@ -5,6 +5,7 @@ import prog8.ast.base.*
|
|||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.processing.AstWalker
|
import prog8.ast.processing.AstWalker
|
||||||
import prog8.ast.processing.IAstVisitor
|
import prog8.ast.processing.IAstVisitor
|
||||||
|
import prog8.compiler.target.CompilationTarget
|
||||||
|
|
||||||
|
|
||||||
sealed class Statement : Node {
|
sealed class Statement : Node {
|
||||||
@ -392,8 +393,8 @@ data class AssignTarget(var identifier: IdentifierReference?,
|
|||||||
|
|
||||||
override fun replaceChildNode(node: Node, replacement: Node) {
|
override fun replaceChildNode(node: Node, replacement: Node) {
|
||||||
when {
|
when {
|
||||||
node===identifier -> identifier = replacement as IdentifierReference
|
node === identifier -> identifier = replacement as IdentifierReference
|
||||||
node===arrayindexed -> arrayindexed = replacement as ArrayIndexedExpression
|
node === arrayindexed -> arrayindexed = replacement as ArrayIndexedExpression
|
||||||
else -> throw FatalAstException("invalid replace")
|
else -> throw FatalAstException("invalid replace")
|
||||||
}
|
}
|
||||||
replacement.parent = this
|
replacement.parent = this
|
||||||
@ -414,16 +415,16 @@ data class AssignTarget(var identifier: IdentifierReference?,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun inferType(program: Program, stmt: Statement): InferredTypes.InferredType {
|
fun inferType(program: Program, stmt: Statement): InferredTypes.InferredType {
|
||||||
if(identifier!=null) {
|
if (identifier != null) {
|
||||||
val symbol = program.namespace.lookup(identifier!!.nameInSource, stmt) ?: return InferredTypes.unknown()
|
val symbol = program.namespace.lookup(identifier!!.nameInSource, stmt) ?: return InferredTypes.unknown()
|
||||||
if (symbol is VarDecl) return InferredTypes.knownFor(symbol.datatype)
|
if (symbol is VarDecl) return InferredTypes.knownFor(symbol.datatype)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(arrayindexed!=null) {
|
if (arrayindexed != null) {
|
||||||
return arrayindexed!!.inferType(program)
|
return arrayindexed!!.inferType(program)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(memoryAddress!=null)
|
if (memoryAddress != null)
|
||||||
return InferredTypes.knownFor(DataType.UBYTE)
|
return InferredTypes.knownFor(DataType.UBYTE)
|
||||||
|
|
||||||
return InferredTypes.unknown()
|
return InferredTypes.unknown()
|
||||||
@ -431,69 +432,92 @@ data class AssignTarget(var identifier: IdentifierReference?,
|
|||||||
|
|
||||||
fun toExpression(): Expression {
|
fun toExpression(): Expression {
|
||||||
return when {
|
return when {
|
||||||
identifier!=null -> identifier!!
|
identifier != null -> identifier!!
|
||||||
arrayindexed!=null -> arrayindexed!!
|
arrayindexed != null -> arrayindexed!!
|
||||||
memoryAddress!=null -> DirectMemoryRead(memoryAddress.addressExpression, memoryAddress.position)
|
memoryAddress != null -> DirectMemoryRead(memoryAddress.addressExpression, memoryAddress.position)
|
||||||
else -> throw FatalAstException("invalid assignmenttarget $this")
|
else -> throw FatalAstException("invalid assignmenttarget $this")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun isSameAs(value: Expression): Boolean {
|
infix fun isSameAs(value: Expression): Boolean {
|
||||||
return when {
|
return when {
|
||||||
this.memoryAddress!=null -> {
|
this.memoryAddress != null -> {
|
||||||
// if the target is a memory write, and the value is a memory read, they're the same if the address matches
|
// if the target is a memory write, and the value is a memory read, they're the same if the address matches
|
||||||
if(value is DirectMemoryRead)
|
if (value is DirectMemoryRead)
|
||||||
this.memoryAddress.addressExpression isSameAs value.addressExpression
|
this.memoryAddress.addressExpression isSameAs value.addressExpression
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
this.identifier!=null -> value is IdentifierReference && value.nameInSource==identifier!!.nameInSource
|
this.identifier != null -> value is IdentifierReference && value.nameInSource == identifier!!.nameInSource
|
||||||
this.arrayindexed!=null -> value is ArrayIndexedExpression &&
|
this.arrayindexed != null -> value is ArrayIndexedExpression &&
|
||||||
value.identifier.nameInSource==arrayindexed!!.identifier.nameInSource &&
|
value.identifier.nameInSource == arrayindexed!!.identifier.nameInSource &&
|
||||||
value.arrayspec.constIndex()!=null &&
|
value.arrayspec.constIndex() != null &&
|
||||||
arrayindexed!!.arrayspec.constIndex()!=null &&
|
arrayindexed!!.arrayspec.constIndex() != null &&
|
||||||
value.arrayspec.constIndex()==arrayindexed!!.arrayspec.constIndex()
|
value.arrayspec.constIndex() == arrayindexed!!.arrayspec.constIndex()
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isSameAs(other: AssignTarget, program: Program): Boolean {
|
fun isSameAs(other: AssignTarget, program: Program): Boolean {
|
||||||
if(this===other)
|
if (this === other)
|
||||||
return true
|
return true
|
||||||
if(this.identifier!=null && other.identifier!=null)
|
if (this.identifier != null && other.identifier != null)
|
||||||
return this.identifier!!.nameInSource==other.identifier!!.nameInSource
|
return this.identifier!!.nameInSource == other.identifier!!.nameInSource
|
||||||
if(this.memoryAddress!=null && other.memoryAddress!=null) {
|
if (this.memoryAddress != null && other.memoryAddress != null) {
|
||||||
val addr1 = this.memoryAddress.addressExpression.constValue(program)
|
val addr1 = this.memoryAddress.addressExpression.constValue(program)
|
||||||
val addr2 = other.memoryAddress.addressExpression.constValue(program)
|
val addr2 = other.memoryAddress.addressExpression.constValue(program)
|
||||||
return addr1!=null && addr2!=null && addr1==addr2
|
return addr1 != null && addr2 != null && addr1 == addr2
|
||||||
}
|
}
|
||||||
if(this.arrayindexed!=null && other.arrayindexed!=null) {
|
if (this.arrayindexed != null && other.arrayindexed != null) {
|
||||||
if(this.arrayindexed!!.identifier.nameInSource == other.arrayindexed!!.identifier.nameInSource) {
|
if (this.arrayindexed!!.identifier.nameInSource == other.arrayindexed!!.identifier.nameInSource) {
|
||||||
val x1 = this.arrayindexed!!.arrayspec.index.constValue(program)
|
val x1 = this.arrayindexed!!.arrayspec.index.constValue(program)
|
||||||
val x2 = other.arrayindexed!!.arrayspec.index.constValue(program)
|
val x2 = other.arrayindexed!!.arrayspec.index.constValue(program)
|
||||||
return x1!=null && x2!=null && x1==x2
|
return x1 != null && x2 != null && x1 == x2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isNotMemory(namespace: INameScope): Boolean {
|
fun isInRegularRAM(namespace: INameScope): Boolean {
|
||||||
if(this.memoryAddress!=null)
|
when {
|
||||||
return false
|
this.memoryAddress != null -> {
|
||||||
if(this.arrayindexed!=null) {
|
return when (this.memoryAddress.addressExpression) {
|
||||||
|
is NumericLiteralValue -> {
|
||||||
|
CompilationTarget.instance.machine.isRegularRAMaddress((this.memoryAddress.addressExpression as NumericLiteralValue).number.toInt())
|
||||||
|
}
|
||||||
|
is IdentifierReference -> {
|
||||||
|
val decl = (this.memoryAddress.addressExpression as IdentifierReference).targetVarDecl(namespace)
|
||||||
|
if ((decl?.type == VarDeclType.VAR || decl?.type == VarDeclType.CONST) && decl.value is NumericLiteralValue)
|
||||||
|
CompilationTarget.instance.machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt())
|
||||||
|
else
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.arrayindexed != null -> {
|
||||||
val targetStmt = this.arrayindexed!!.identifier.targetVarDecl(namespace)
|
val targetStmt = this.arrayindexed!!.identifier.targetVarDecl(namespace)
|
||||||
if(targetStmt!=null)
|
return if (targetStmt?.type == VarDeclType.MEMORY) {
|
||||||
return targetStmt.type!= VarDeclType.MEMORY
|
val addr = targetStmt.value as? NumericLiteralValue
|
||||||
|
if (addr != null)
|
||||||
|
CompilationTarget.instance.machine.isRegularRAMaddress(addr.number.toInt())
|
||||||
|
else
|
||||||
|
false
|
||||||
|
} else true
|
||||||
}
|
}
|
||||||
if(this.identifier!=null) {
|
this.identifier != null -> {
|
||||||
val targetStmt = this.identifier!!.targetVarDecl(namespace)
|
val decl = this.identifier!!.targetVarDecl(namespace)!!
|
||||||
if(targetStmt!=null)
|
return if (decl.type == VarDeclType.MEMORY && decl.value is NumericLiteralValue)
|
||||||
return targetStmt.type!= VarDeclType.MEMORY
|
CompilationTarget.instance.machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt())
|
||||||
|
else
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> return true
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PostIncrDecr(var target: AssignTarget, val operator: String, override val position: Position) : Statement() {
|
class PostIncrDecr(var target: AssignTarget, val operator: String, override val position: Position) : Statement() {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
|
||||||
|
@ -17,7 +17,12 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
|
|||||||
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||||
subroutineVariables.add(Pair(decl.name, decl))
|
subroutineVariables.add(Pair(decl.name, decl))
|
||||||
if (decl.value == null && !decl.autogeneratedDontRemove && decl.type == VarDeclType.VAR && decl.datatype in NumericDatatypes) {
|
if (decl.value == null && !decl.autogeneratedDontRemove && decl.type == VarDeclType.VAR && decl.datatype in NumericDatatypes) {
|
||||||
// a numeric vardecl without an initial value is initialized with zero.
|
// a numeric vardecl without an initial value is initialized with zero,
|
||||||
|
// unless there's already an assignment below, that initializes the value
|
||||||
|
val nextAssign = decl.definingScope().nextSibling(decl) as? Assignment
|
||||||
|
if(nextAssign!=null && nextAssign.target.isSameAs(IdentifierReference(listOf(decl.name), Position.DUMMY)))
|
||||||
|
decl.value = null
|
||||||
|
else
|
||||||
decl.value = decl.zeroElementValue()
|
decl.value = decl.zeroElementValue()
|
||||||
}
|
}
|
||||||
return noModifications
|
return noModifications
|
||||||
@ -29,7 +34,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
|
|||||||
// But it can only be done if the target variable IS NOT OCCURRING AS AN OPERAND ITSELF.
|
// But it can only be done if the target variable IS NOT OCCURRING AS AN OPERAND ITSELF.
|
||||||
if(!assignment.isAugmentable
|
if(!assignment.isAugmentable
|
||||||
&& assignment.target.identifier != null
|
&& assignment.target.identifier != null
|
||||||
&& assignment.target.isNotMemory(program.namespace)) {
|
&& assignment.target.isInRegularRAM(program.namespace)) {
|
||||||
val binExpr = assignment.value as? BinaryExpression
|
val binExpr = assignment.value as? BinaryExpression
|
||||||
if (binExpr != null && binExpr.operator !in comparisonOperators) {
|
if (binExpr != null && binExpr.operator !in comparisonOperators) {
|
||||||
if (binExpr.left !is BinaryExpression) {
|
if (binExpr.left !is BinaryExpression) {
|
||||||
|
@ -195,7 +195,7 @@ private fun optimizeAst(programAst: Program, errors: ErrorReporter) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
val remover = UnusedCodeRemover(errors)
|
val remover = UnusedCodeRemover(programAst, errors)
|
||||||
remover.visit(programAst)
|
remover.visit(programAst)
|
||||||
remover.applyModifications()
|
remover.applyModifications()
|
||||||
errors.handle()
|
errors.handle()
|
||||||
@ -218,7 +218,7 @@ private fun writeAssembly(programAst: Program, errors: ErrorReporter, outputDir:
|
|||||||
programAst.processAstBeforeAsmGeneration(errors)
|
programAst.processAstBeforeAsmGeneration(errors)
|
||||||
errors.handle()
|
errors.handle()
|
||||||
|
|
||||||
// printAst(programAst)
|
printAst(programAst) // TODO
|
||||||
|
|
||||||
CompilationTarget.instance.machine.initializeZeropage(compilerOptions)
|
CompilationTarget.instance.machine.initializeZeropage(compilerOptions)
|
||||||
val assembly = CompilationTarget.instance.asmGenerator(
|
val assembly = CompilationTarget.instance.asmGenerator(
|
||||||
|
@ -35,5 +35,5 @@ internal interface IMachineDefinition {
|
|||||||
fun getFloatRomConst(number: Double): String?
|
fun getFloatRomConst(number: Double): String?
|
||||||
fun importLibs(compilerOptions: CompilationOptions, importer: ModuleImporter, program: Program)
|
fun importLibs(compilerOptions: CompilationOptions, importer: ModuleImporter, program: Program)
|
||||||
fun launchEmulator(programName: String)
|
fun launchEmulator(programName: String)
|
||||||
fun isRAMaddress(address: Int): Boolean
|
fun isRegularRAMaddress(address: Int): Boolean
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ internal object C64MachineDefinition: IMachineDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isRAMaddress(address: Int): Boolean = (address<0xa000) || (address in 0xc000..0xd000)
|
override fun isRegularRAMaddress(address: Int): Boolean = address<0xa000 || address in 0xc000..0xcfff
|
||||||
|
|
||||||
override fun initializeZeropage(compilerOptions: CompilationOptions) {
|
override fun initializeZeropage(compilerOptions: CompilationOptions) {
|
||||||
zeropage = C64Zeropage(compilerOptions)
|
zeropage = C64Zeropage(compilerOptions)
|
||||||
|
@ -52,9 +52,7 @@ internal object CX16MachineDefinition: IMachineDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isRAMaddress(address: Int): Boolean {
|
override fun isRegularRAMaddress(address: Int): Boolean = address < 0x9f00 || address in 0xa000..0xbfff
|
||||||
return address < 0x9000 // TODO put correct Cx16 mem ranges here
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun initializeZeropage(compilerOptions: CompilationOptions) {
|
override fun initializeZeropage(compilerOptions: CompilationOptions) {
|
||||||
zeropage = CX16Zeropage(compilerOptions)
|
zeropage = CX16Zeropage(compilerOptions)
|
||||||
|
@ -49,11 +49,6 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val linesToRemove = deduplicateAssignments(subroutine.statements)
|
|
||||||
if(linesToRemove.isNotEmpty()) {
|
|
||||||
linesToRemove.reversed().forEach{subroutine.statements.removeAt(it)}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(subroutine !in callgraph.usedSymbols && !forceOutput) {
|
if(subroutine !in callgraph.usedSymbols && !forceOutput) {
|
||||||
errors.warn("removing unused subroutine '${subroutine.name}'", subroutine.position)
|
errors.warn("removing unused subroutine '${subroutine.name}'", subroutine.position)
|
||||||
return listOf(IAstModification.Remove(subroutine, parent))
|
return listOf(IAstModification.Remove(subroutine, parent))
|
||||||
@ -62,11 +57,6 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun after(scope: AnonymousScope, parent: Node): Iterable<IAstModification> {
|
|
||||||
val linesToRemove = deduplicateAssignments(scope.statements)
|
|
||||||
return linesToRemove.reversed().map { IAstModification.Remove(scope.statements[it], scope) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||||
val forceOutput = "force_output" in decl.definingBlock().options()
|
val forceOutput = "force_output" in decl.definingBlock().options()
|
||||||
if(decl !in callgraph.usedSymbols && !forceOutput) {
|
if(decl !in callgraph.usedSymbols && !forceOutput) {
|
||||||
@ -447,36 +437,16 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isSimpleTarget(target: AssignTarget): Boolean {
|
fun isSimpleTarget(target: AssignTarget, namespace: INameScope): Boolean {
|
||||||
return when {
|
return when {
|
||||||
target.identifier!=null -> {
|
target.identifier!=null -> target.isInRegularRAM(namespace)
|
||||||
val decl = target.identifier!!.targetVarDecl(program.namespace)!!
|
target.memoryAddress!=null -> target.isInRegularRAM(namespace)
|
||||||
return if(decl.type!=VarDeclType.MEMORY) {
|
|
||||||
if(decl.value is NumericLiteralValue) {
|
|
||||||
CompilationTarget.instance.machine.isRAMaddress((decl.value as NumericLiteralValue).number.toInt())
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else true
|
|
||||||
}
|
|
||||||
target.memoryAddress!=null -> {
|
|
||||||
return when (target.memoryAddress.addressExpression) {
|
|
||||||
is NumericLiteralValue -> {
|
|
||||||
CompilationTarget.instance.machine.isRAMaddress((target.memoryAddress.addressExpression as NumericLiteralValue).number.toInt())
|
|
||||||
}
|
|
||||||
is IdentifierReference -> {
|
|
||||||
val decl = (target.memoryAddress.addressExpression as IdentifierReference).targetVarDecl(program.namespace)!!
|
|
||||||
if(decl.value is NumericLiteralValue) {
|
|
||||||
CompilationTarget.instance.machine.isRAMaddress((decl.value as NumericLiteralValue).number.toInt())
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
target.arrayindexed!=null -> {
|
target.arrayindexed!=null -> {
|
||||||
target.arrayindexed!!.arrayspec.index is NumericLiteralValue
|
val index = target.arrayindexed!!.arrayspec.index
|
||||||
|
if(index is NumericLiteralValue || index is IdentifierReference)
|
||||||
|
target.isInRegularRAM(namespace)
|
||||||
|
else
|
||||||
|
false
|
||||||
}
|
}
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
@ -487,51 +457,27 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
// X = <some-expression-not-X> <operator> <not-binary-expression>
|
// X = <some-expression-not-X> <operator> <not-binary-expression>
|
||||||
// or X = <not-binary-expression> <associativeoperator> <some-expression-not-X>
|
// or X = <not-binary-expression> <associativeoperator> <some-expression-not-X>
|
||||||
// split that into X = <some-expression-not-X> ; X = X <operator> <not-binary-expression>
|
// split that into X = <some-expression-not-X> ; X = X <operator> <not-binary-expression>
|
||||||
if(bexpr.operator !in comparisonOperators && !assignment.isAugmentable && isSimpleTarget(assignment.target)) {
|
// TODO FIX THIS SPLITTING (IT ENDS UP IN A LOOP SOMETIMES)
|
||||||
if (bexpr.right !is BinaryExpression) {
|
// if(bexpr.operator !in comparisonOperators && !assignment.isAugmentable && isSimpleTarget(assignment.target, program.namespace)) {
|
||||||
val firstAssign = Assignment(assignment.target, bexpr.left, assignment.position)
|
// if (bexpr.right !is BinaryExpression) {
|
||||||
val augExpr = BinaryExpression(assignment.target.toExpression(), bexpr.operator, bexpr.right, bexpr.position)
|
// val firstAssign = Assignment(assignment.target, bexpr.left, assignment.position)
|
||||||
return listOf(
|
// val augExpr = BinaryExpression(assignment.target.toExpression(), bexpr.operator, bexpr.right, bexpr.position)
|
||||||
IAstModification.InsertBefore(assignment, firstAssign, parent),
|
// return listOf(
|
||||||
IAstModification.ReplaceNode(assignment.value, augExpr, assignment))
|
// IAstModification.InsertBefore(assignment, firstAssign, parent),
|
||||||
} else if (bexpr.left !is BinaryExpression && bexpr.operator in associativeOperators) {
|
// IAstModification.ReplaceNode(assignment.value, augExpr, assignment))
|
||||||
val firstAssign = Assignment(assignment.target, bexpr.right, assignment.position)
|
// } else if (bexpr.left !is BinaryExpression && bexpr.operator in associativeOperators) {
|
||||||
val augExpr = BinaryExpression(assignment.target.toExpression(), bexpr.operator, bexpr.left, bexpr.position)
|
// val firstAssign = Assignment(assignment.target, bexpr.right, assignment.position)
|
||||||
return listOf(
|
// val augExpr = BinaryExpression(assignment.target.toExpression(), bexpr.operator, bexpr.left, bexpr.position)
|
||||||
IAstModification.InsertBefore(assignment, firstAssign, parent),
|
// return listOf(
|
||||||
IAstModification.ReplaceNode(assignment.value, augExpr, assignment))
|
// IAstModification.InsertBefore(assignment, firstAssign, parent),
|
||||||
}
|
// IAstModification.ReplaceNode(assignment.value, augExpr, assignment))
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deduplicateAssignments(statements: List<Statement>): MutableList<Int> {
|
|
||||||
// removes 'duplicate' assignments that assign the isSameAs target
|
|
||||||
val linesToRemove = mutableListOf<Int>()
|
|
||||||
var previousAssignmentLine: Int? = null
|
|
||||||
for (i in statements.indices) {
|
|
||||||
val stmt = statements[i] as? Assignment
|
|
||||||
if (stmt != null && stmt.value is NumericLiteralValue) {
|
|
||||||
if (previousAssignmentLine == null) {
|
|
||||||
previousAssignmentLine = i
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
val prev = statements[previousAssignmentLine] as Assignment
|
|
||||||
if (prev.target.isSameAs(stmt.target, program)) {
|
|
||||||
// get rid of the previous assignment, if the target is not MEMORY
|
|
||||||
if (prev.target.isNotMemory(program.namespace))
|
|
||||||
linesToRemove.add(previousAssignmentLine)
|
|
||||||
}
|
|
||||||
previousAssignmentLine = i
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
previousAssignmentLine = null
|
|
||||||
}
|
|
||||||
return linesToRemove
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hasBreak(scope: INameScope): Boolean {
|
private fun hasBreak(scope: INameScope): Boolean {
|
||||||
|
|
||||||
class Searcher: IAstVisitor
|
class Searcher: IAstVisitor
|
||||||
|
@ -4,6 +4,7 @@ import prog8.ast.INameScope
|
|||||||
import prog8.ast.Node
|
import prog8.ast.Node
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.ErrorReporter
|
import prog8.ast.base.ErrorReporter
|
||||||
|
import prog8.ast.expressions.NumericLiteralValue
|
||||||
import prog8.ast.processing.AstWalker
|
import prog8.ast.processing.AstWalker
|
||||||
import prog8.ast.processing.IAstModification
|
import prog8.ast.processing.IAstModification
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
@ -11,7 +12,7 @@ import prog8.ast.statements.*
|
|||||||
|
|
||||||
// TODO remove unneeded assignments such as: cc = 0 ; cc= xbuf ; ... the first can be removed (unless target is not RAM)
|
// TODO remove unneeded assignments such as: cc = 0 ; cc= xbuf ; ... the first can be removed (unless target is not RAM)
|
||||||
|
|
||||||
internal class UnusedCodeRemover(private val errors: ErrorReporter): AstWalker() {
|
internal class UnusedCodeRemover(private val program: Program, private val errors: ErrorReporter): AstWalker() {
|
||||||
|
|
||||||
override fun before(program: Program, parent: Node): Iterable<IAstModification> {
|
override fun before(program: Program, parent: Node): Iterable<IAstModification> {
|
||||||
val callgraph = CallGraph(program)
|
val callgraph = CallGraph(program)
|
||||||
@ -69,4 +70,36 @@ internal class UnusedCodeRemover(private val errors: ErrorReporter): AstWalker()
|
|||||||
else -> errors.warn("unreachable code", next.position)
|
else -> errors.warn("unreachable code", next.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun after(scope: AnonymousScope, parent: Node): Iterable<IAstModification> {
|
||||||
|
val removeDoubleAssignments = deduplicateAssignments(scope.statements)
|
||||||
|
return removeDoubleAssignments.map { IAstModification.Remove(it, scope) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
|
||||||
|
val removeDoubleAssignments = deduplicateAssignments(block.statements)
|
||||||
|
return removeDoubleAssignments.map { IAstModification.Remove(it, block) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> {
|
||||||
|
val removeDoubleAssignments = deduplicateAssignments(subroutine.statements)
|
||||||
|
return removeDoubleAssignments.map { IAstModification.Remove(it, subroutine) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// subroutine, anonscope,
|
||||||
|
private fun deduplicateAssignments(statements: List<Statement>): List<Assignment> {
|
||||||
|
// removes 'duplicate' assignments that assign the isSameAs target
|
||||||
|
val linesToRemove = mutableListOf<Assignment>()
|
||||||
|
|
||||||
|
for (stmtPairs in statements.windowed(2, step = 1)) {
|
||||||
|
val assign1 = stmtPairs[0] as? Assignment
|
||||||
|
val assign2 = stmtPairs[1] as? Assignment
|
||||||
|
if (assign1 != null && assign2 != null) {
|
||||||
|
if (assign1.target.isSameAs(assign2.target, program) && assign1.target.isInRegularRAM(program.namespace))
|
||||||
|
linesToRemove.add(assign1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return linesToRemove
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,18 +5,21 @@ import org.hamcrest.Matchers.closeTo
|
|||||||
import org.hamcrest.Matchers.equalTo
|
import org.hamcrest.Matchers.equalTo
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.TestInstance
|
import org.junit.jupiter.api.TestInstance
|
||||||
import prog8.ast.base.DataType
|
import prog8.ast.Module
|
||||||
import prog8.ast.base.ErrorReporter
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.Position
|
import prog8.ast.base.*
|
||||||
import prog8.ast.expressions.NumericLiteralValue
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.expressions.StringLiteralValue
|
import prog8.ast.statements.*
|
||||||
import prog8.compiler.*
|
import prog8.compiler.*
|
||||||
|
import prog8.compiler.target.C64Target
|
||||||
|
import prog8.compiler.target.CompilationTarget
|
||||||
import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage
|
import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage
|
||||||
import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_NEGATIVE
|
import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_NEGATIVE
|
||||||
import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_POSITIVE
|
import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_POSITIVE
|
||||||
import prog8.compiler.target.c64.C64MachineDefinition.Mflpt5
|
import prog8.compiler.target.c64.C64MachineDefinition.Mflpt5
|
||||||
import prog8.compiler.target.c64.Petscii
|
import prog8.compiler.target.c64.Petscii
|
||||||
import java.io.CharConversionException
|
import java.io.CharConversionException
|
||||||
|
import java.nio.file.Path
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||||
@ -379,3 +382,169 @@ class TestPetscii {
|
|||||||
assertFalse(abc!=abc)
|
assertFalse(abc!=abc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestMemory {
|
||||||
|
@Test
|
||||||
|
fun testInValidRamC64_memory_addresses() {
|
||||||
|
CompilationTarget.instance = C64Target
|
||||||
|
|
||||||
|
var memexpr = NumericLiteralValue.optimalInteger(0x0000, Position.DUMMY)
|
||||||
|
var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
|
var scope = AnonymousScope(mutableListOf(), Position.DUMMY)
|
||||||
|
assertTrue(target.isInRegularRAM(scope))
|
||||||
|
|
||||||
|
memexpr = NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY)
|
||||||
|
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
|
scope = AnonymousScope(mutableListOf(), Position.DUMMY)
|
||||||
|
assertTrue(target.isInRegularRAM(scope))
|
||||||
|
|
||||||
|
memexpr = NumericLiteralValue.optimalInteger(0x9fff, Position.DUMMY)
|
||||||
|
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
|
scope = AnonymousScope(mutableListOf(), Position.DUMMY)
|
||||||
|
assertTrue(target.isInRegularRAM(scope))
|
||||||
|
|
||||||
|
memexpr = NumericLiteralValue.optimalInteger(0xc000, Position.DUMMY)
|
||||||
|
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
|
scope = AnonymousScope(mutableListOf(), Position.DUMMY)
|
||||||
|
assertTrue(target.isInRegularRAM(scope))
|
||||||
|
|
||||||
|
memexpr = NumericLiteralValue.optimalInteger(0xcfff, Position.DUMMY)
|
||||||
|
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
|
scope = AnonymousScope(mutableListOf(), Position.DUMMY)
|
||||||
|
assertTrue(target.isInRegularRAM(scope))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNotInValidRamC64_memory_addresses() {
|
||||||
|
CompilationTarget.instance = C64Target
|
||||||
|
|
||||||
|
var memexpr = NumericLiteralValue.optimalInteger(0xa000, Position.DUMMY)
|
||||||
|
var target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
|
var scope = AnonymousScope(mutableListOf(), Position.DUMMY)
|
||||||
|
assertFalse(target.isInRegularRAM(scope))
|
||||||
|
|
||||||
|
memexpr = NumericLiteralValue.optimalInteger(0xafff, Position.DUMMY)
|
||||||
|
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
|
scope = AnonymousScope(mutableListOf(), Position.DUMMY)
|
||||||
|
assertFalse(target.isInRegularRAM(scope))
|
||||||
|
|
||||||
|
memexpr = NumericLiteralValue.optimalInteger(0xd000, Position.DUMMY)
|
||||||
|
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
|
scope = AnonymousScope(mutableListOf(), Position.DUMMY)
|
||||||
|
assertFalse(target.isInRegularRAM(scope))
|
||||||
|
|
||||||
|
memexpr = NumericLiteralValue.optimalInteger(0xffff, Position.DUMMY)
|
||||||
|
target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
|
scope = AnonymousScope(mutableListOf(), Position.DUMMY)
|
||||||
|
assertFalse(target.isInRegularRAM(scope))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInValidRamC64_memory_identifiers() {
|
||||||
|
CompilationTarget.instance = C64Target
|
||||||
|
var target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.VAR)
|
||||||
|
assertTrue(target.isInRegularRAM(target.definingScope()))
|
||||||
|
target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.VAR)
|
||||||
|
assertFalse(target.isInRegularRAM(target.definingScope()))
|
||||||
|
target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.CONST)
|
||||||
|
assertTrue(target.isInRegularRAM(target.definingScope()))
|
||||||
|
target = createTestProgramForMemoryRefViaVar(0xd020, VarDeclType.CONST)
|
||||||
|
assertFalse(target.isInRegularRAM(target.definingScope()))
|
||||||
|
target = createTestProgramForMemoryRefViaVar(0x1000, VarDeclType.MEMORY)
|
||||||
|
assertFalse(target.isInRegularRAM(target.definingScope()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
private fun createTestProgramForMemoryRefViaVar(address: Int, vartype: VarDeclType): AssignTarget {
|
||||||
|
val decl = VarDecl(vartype, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||||
|
val memexpr = IdentifierReference(listOf("address"), Position.DUMMY)
|
||||||
|
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
|
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||||
|
subroutine.linkParents(ParentSentinel)
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInValidRamC64_memory_expression() {
|
||||||
|
CompilationTarget.instance = C64Target
|
||||||
|
val memexpr = PrefixExpression("+", NumericLiteralValue.optimalInteger(0x1000, Position.DUMMY), Position.DUMMY)
|
||||||
|
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), Position.DUMMY)
|
||||||
|
val scope = AnonymousScope(mutableListOf(), Position.DUMMY)
|
||||||
|
assertFalse(target.isInRegularRAM(scope))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInValidRamC64_variable() {
|
||||||
|
CompilationTarget.instance = C64Target
|
||||||
|
val decl = VarDecl(VarDeclType.VAR, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", null, null, false, false, Position.DUMMY)
|
||||||
|
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
||||||
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
|
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||||
|
subroutine.linkParents(ParentSentinel)
|
||||||
|
assertTrue(target.isInRegularRAM(target.definingScope()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInValidRamC64_memmap_variable() {
|
||||||
|
CompilationTarget.instance = C64Target
|
||||||
|
val address = 0x1000
|
||||||
|
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||||
|
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
||||||
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
|
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||||
|
subroutine.linkParents(ParentSentinel)
|
||||||
|
assertTrue(target.isInRegularRAM(target.definingScope()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNotInValidRamC64_memmap_variable() {
|
||||||
|
CompilationTarget.instance = C64Target
|
||||||
|
val address = 0xd020
|
||||||
|
val decl = VarDecl(VarDeclType.MEMORY, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||||
|
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, Position.DUMMY)
|
||||||
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
|
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||||
|
subroutine.linkParents(ParentSentinel)
|
||||||
|
assertFalse(target.isInRegularRAM(target.definingScope()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInValidRamC64_array() {
|
||||||
|
CompilationTarget.instance = C64Target
|
||||||
|
val decl = VarDecl(VarDeclType.VAR, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, null, false, false, Position.DUMMY)
|
||||||
|
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||||
|
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
||||||
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
|
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||||
|
subroutine.linkParents(ParentSentinel)
|
||||||
|
assertTrue(target.isInRegularRAM(target.definingScope()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInValidRamC64_array_memmapped() {
|
||||||
|
CompilationTarget.instance = C64Target
|
||||||
|
val address = 0x1000
|
||||||
|
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||||
|
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||||
|
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
||||||
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
|
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||||
|
subroutine.linkParents(ParentSentinel)
|
||||||
|
assertTrue(target.isInRegularRAM(target.definingScope()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNotValidRamC64_array_memmapped() {
|
||||||
|
CompilationTarget.instance = C64Target
|
||||||
|
val address = 0xe000
|
||||||
|
val decl = VarDecl(VarDeclType.MEMORY, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", null, NumericLiteralValue.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||||
|
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteralValue.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||||
|
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
|
||||||
|
val assignment = Assignment(target, NumericLiteralValue.optimalInteger(0, Position.DUMMY), Position.DUMMY)
|
||||||
|
val subroutine = Subroutine("test", emptyList(), emptyList(), emptyList(), emptyList(), emptySet(), null, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||||
|
subroutine.linkParents(ParentSentinel)
|
||||||
|
assertFalse(target.isInRegularRAM(target.definingScope()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -74,12 +74,12 @@ main {
|
|||||||
}
|
}
|
||||||
c2A += 2
|
c2A += 2
|
||||||
c2B -= 3
|
c2B -= 3
|
||||||
ubyte cc
|
|
||||||
|
|
||||||
for y in 24 downto 0 {
|
for y in 24 downto 0 {
|
||||||
for x in 39 downto 0 {
|
for x in 39 downto 0 {
|
||||||
; using a temp var here to enable expression optimization that can't be done on a 'problematic' ROM/RAM memory location
|
; using a temp var here to enable expression optimization that can't be done on a 'problematic' ROM/RAM memory location
|
||||||
ubyte cc = xbuf[x] + ybuf[y] ; TODO should be split!!
|
ubyte cc
|
||||||
|
cc = xbuf[x] + ybuf[y] ; TODO should be split!!
|
||||||
@(screen) = cc
|
@(screen) = cc
|
||||||
; this is the fastest way to do this inner part:
|
; this is the fastest way to do this inner part:
|
||||||
; %asm {{
|
; %asm {{
|
||||||
|
@ -37,8 +37,8 @@ _saveX .byte 0
|
|||||||
sub start() {
|
sub start() {
|
||||||
; byte bb = 100
|
; byte bb = 100
|
||||||
; word ww = 30000
|
; word ww = 30000
|
||||||
float ff1 = 1000
|
; float ff1 = 1000
|
||||||
float ff2 = -1000
|
; float ff2 = -1000
|
||||||
|
|
||||||
|
|
||||||
ubyte[10] xbuf
|
ubyte[10] xbuf
|
||||||
@ -46,22 +46,21 @@ _saveX .byte 0
|
|||||||
ubyte x
|
ubyte x
|
||||||
ubyte y
|
ubyte y
|
||||||
|
|
||||||
ubyte cc = xbuf[x] + ybuf[y] ; TODO should be split!!
|
ubyte cc = xbuf[x] + ybuf[y] ; TODO should be split!! also fix plasma.p8
|
||||||
ubyte cc2
|
ubyte cc2
|
||||||
cc2 = xbuf[x] + ybuf[y] ; will be split correctly?
|
cc2 = xbuf[x] + ybuf[y] +cc ; will be split correctly.
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
ff1 = 1+((-ff1) *3)
|
; ff1 = 1+((-ff1) *3)
|
||||||
floats.print_f(ff1)
|
; floats.print_f(ff1)
|
||||||
floats.print_f(1+((-1000) *3))
|
; floats.print_f(1+((-1000) *3))
|
||||||
testX()
|
; testX()
|
||||||
ff1 = 1+((-ff2) *3)
|
; ff1 = 1+((-ff2) *3)
|
||||||
floats.print_f(ff1)
|
; floats.print_f(ff1)
|
||||||
floats.print_f(1+((- (-1000)) *3))
|
; floats.print_f(1+((- (-1000)) *3))
|
||||||
txt.chrout('\n')
|
; txt.chrout('\n')
|
||||||
testX()
|
; testX()
|
||||||
return
|
; return
|
||||||
|
|
||||||
; struct Color {
|
; struct Color {
|
||||||
; ubyte red
|
; ubyte red
|
||||||
|
Loading…
Reference in New Issue
Block a user