mirror of
https://github.com/irmen/prog8.git
synced 2024-06-14 00:29:34 +00:00
removed postIncrDecr (still allow ++/-- to be parsed into +=1/-=1)
This commit is contained in:
parent
f874942075
commit
358215e4dd
|
@ -123,7 +123,6 @@ fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Uni
|
|||
}
|
||||
is PtNodeGroup -> "<group>"
|
||||
is PtNop -> "nop"
|
||||
is PtPostIncrDecr -> "<post> ${node.operator}"
|
||||
is PtProgram -> "PROGRAM ${node.name}"
|
||||
is PtRepeatLoop -> "repeat"
|
||||
is PtReturn -> "return"
|
||||
|
|
|
@ -110,12 +110,6 @@ class PtJump(val identifier: PtIdentifier?, // note: even ad-hoc labels are
|
|||
}
|
||||
|
||||
|
||||
class PtPostIncrDecr(val operator: String, position: Position) : PtNode(position) {
|
||||
val target: PtAssignTarget
|
||||
get() = children.single() as PtAssignTarget
|
||||
}
|
||||
|
||||
|
||||
class PtRepeatLoop(position: Position) : PtNode(position) {
|
||||
val count: PtExpression
|
||||
get() = children[0] as PtExpression
|
||||
|
|
|
@ -227,7 +227,6 @@ class AsmGen6502Internal (
|
|||
private val assembly = mutableListOf<String>()
|
||||
private val breakpointLabels = mutableListOf<String>()
|
||||
private val forloopsAsmGen = ForLoopsAsmGen(this, zeropage)
|
||||
private val postincrdecrAsmGen = PostIncrDecrAsmGen(program, this)
|
||||
private val functioncallAsmGen = FunctionCallAsmGen(program, this)
|
||||
private val programGen = ProgramAndVarsGen(program, options, errors, symbolTable, functioncallAsmGen, this, allocator, zeropage)
|
||||
private val anyExprGen = AnyExprAsmGen(this)
|
||||
|
@ -535,7 +534,6 @@ class AsmGen6502Internal (
|
|||
val (asmLabel, indirect) = getJumpTarget(stmt)
|
||||
jmp(asmLabel, indirect)
|
||||
}
|
||||
is PtPostIncrDecr -> postincrdecrAsmGen.translate(stmt)
|
||||
is PtLabel -> translate(stmt)
|
||||
is PtConditionalBranch -> translate(stmt)
|
||||
is PtIfElse -> translate(stmt)
|
||||
|
|
|
@ -1,191 +0,0 @@
|
|||
package prog8.codegen.cpu6502
|
||||
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
|
||||
|
||||
internal class PostIncrDecrAsmGen(private val program: PtProgram, private val asmgen: AsmGen6502Internal) {
|
||||
internal fun translate(stmt: PtPostIncrDecr) {
|
||||
val incr = stmt.operator=="++"
|
||||
val targetIdent = stmt.target.identifier
|
||||
val targetMemory = stmt.target.memory
|
||||
val targetArrayIdx = stmt.target.array
|
||||
when {
|
||||
targetIdent!=null -> {
|
||||
val what = asmgen.asmVariableName(targetIdent)
|
||||
when (stmt.target.type) {
|
||||
in ByteDatatypes -> asmgen.out(if (incr) " inc $what" else " dec $what")
|
||||
in WordDatatypes -> {
|
||||
if(incr)
|
||||
asmgen.out(" inc $what | bne + | inc $what+1 |+")
|
||||
else
|
||||
asmgen.out("""
|
||||
lda $what
|
||||
bne +
|
||||
dec $what+1
|
||||
+ dec $what
|
||||
""")
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
asmgen.out(" lda #<$what | ldy #>$what")
|
||||
asmgen.out(if(incr) " jsr floats.inc_var_f" else " jsr floats.dec_var_f")
|
||||
}
|
||||
else -> throw AssemblyError("need numeric type")
|
||||
}
|
||||
}
|
||||
targetMemory!=null -> {
|
||||
fun incDecViaExprEval() {
|
||||
asmgen.assignExpressionToRegister(targetMemory.address, RegisterOrPair.AY)
|
||||
asmgen.out(" sta (+) + 1 | sty (+) + 2")
|
||||
if(incr)
|
||||
asmgen.out("+\tinc ${'$'}ffff\t; modified")
|
||||
else
|
||||
asmgen.out("+\tdec ${'$'}ffff\t; modified")
|
||||
}
|
||||
|
||||
fun tryOptimizedPointerIncDec(address: PtBinaryExpression): Boolean {
|
||||
if(address.operator=="+") {
|
||||
val offset = address.right.asConstInteger()
|
||||
if(offset!=null && offset<256) {
|
||||
// we have @(ptr + 255) ++ , or @(ptr+255)--
|
||||
asmgen.assignExpressionToRegister(address.left, RegisterOrPair.AY, false)
|
||||
asmgen.out("""
|
||||
sta (+) + 1
|
||||
sty (+) + 2
|
||||
ldx #$offset""")
|
||||
if(incr)
|
||||
asmgen.out("+\tinc ${'$'}ffff,x\t; modified")
|
||||
else
|
||||
asmgen.out("+\tdec ${'$'}ffff,x\t; modified")
|
||||
return true
|
||||
} else if(address.right.type in ByteDatatypes) {
|
||||
// we have @(ptr + bytevar) ++ , or @(ptr+bytevar)--
|
||||
asmgen.assignExpressionToRegister(address.left, RegisterOrPair.AY, false)
|
||||
asmgen.out(" sta (+) + 1 | sty (+) + 2")
|
||||
asmgen.assignExpressionToRegister(address.right, RegisterOrPair.X, false)
|
||||
if(incr)
|
||||
asmgen.out("+\tinc ${'$'}ffff,x\t; modified")
|
||||
else
|
||||
asmgen.out("+\tdec ${'$'}ffff,x\t; modified")
|
||||
return true
|
||||
} else if((address.right as? PtTypeCast)?.value?.type in ByteDatatypes) {
|
||||
// we have @(ptr + bytevar) ++ , or @(ptr+bytevar)--
|
||||
asmgen.assignExpressionToRegister(address.left, RegisterOrPair.AY, false)
|
||||
asmgen.out(" sta (+) + 1 | sty (+) + 2")
|
||||
asmgen.assignExpressionToRegister((address.right as PtTypeCast).value, RegisterOrPair.X, false)
|
||||
if(incr)
|
||||
asmgen.out("+\tinc ${'$'}ffff,x\t; modified")
|
||||
else
|
||||
asmgen.out("+\tdec ${'$'}ffff,x\t; modified")
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
when (val addressExpr = targetMemory.address) {
|
||||
is PtNumber -> {
|
||||
val what = addressExpr.number.toHex()
|
||||
asmgen.out(if(incr) " inc $what" else " dec $what")
|
||||
}
|
||||
is PtIdentifier -> {
|
||||
val what = asmgen.asmVariableName(addressExpr)
|
||||
asmgen.out(" lda $what | sta (+) +1 | lda $what+1 | sta (+) +2")
|
||||
if(incr)
|
||||
asmgen.out("+\tinc ${'$'}ffff\t; modified")
|
||||
else
|
||||
asmgen.out("+\tdec ${'$'}ffff\t; modified")
|
||||
}
|
||||
is PtBinaryExpression -> {
|
||||
if(!tryOptimizedPointerIncDec(addressExpr)) {
|
||||
incDecViaExprEval()
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
incDecViaExprEval()
|
||||
}
|
||||
}
|
||||
}
|
||||
targetArrayIdx!=null -> {
|
||||
val asmArrayvarname = asmgen.asmVariableName(targetArrayIdx.variable)
|
||||
val elementDt = targetArrayIdx.type
|
||||
val constIndex = targetArrayIdx.index.asConstInteger()
|
||||
if(targetArrayIdx.splitWords) {
|
||||
if(constIndex!=null) {
|
||||
if(incr)
|
||||
asmgen.out(" inc ${asmArrayvarname}_lsb+$constIndex | bne + | inc ${asmArrayvarname}_msb+$constIndex |+")
|
||||
else
|
||||
asmgen.out("""
|
||||
lda ${asmArrayvarname}_lsb+$constIndex
|
||||
bne +
|
||||
dec ${asmArrayvarname}_msb+$constIndex
|
||||
+ dec ${asmArrayvarname}_lsb+$constIndex""")
|
||||
} else {
|
||||
asmgen.loadScaledArrayIndexIntoRegister(targetArrayIdx, CpuRegister.X)
|
||||
if(incr)
|
||||
asmgen.out(" inc ${asmArrayvarname}_lsb,x | bne + | inc ${asmArrayvarname}_msb,x |+")
|
||||
else
|
||||
asmgen.out("""
|
||||
lda ${asmArrayvarname}_lsb,x
|
||||
bne +
|
||||
dec ${asmArrayvarname}_msb,x
|
||||
+ dec ${asmArrayvarname}_lsb,x""")
|
||||
}
|
||||
return
|
||||
}
|
||||
if(constIndex!=null) {
|
||||
val indexValue = constIndex * program.memsizer.memorySize(elementDt)
|
||||
when(elementDt) {
|
||||
in ByteDatatypes -> {
|
||||
asmgen.out(if (incr) " inc $asmArrayvarname+$indexValue" else " dec $asmArrayvarname+$indexValue")
|
||||
}
|
||||
in WordDatatypes -> {
|
||||
if(incr)
|
||||
asmgen.out(" inc $asmArrayvarname+$indexValue | bne + | inc $asmArrayvarname+$indexValue+1 |+")
|
||||
else
|
||||
asmgen.out("""
|
||||
lda $asmArrayvarname+$indexValue
|
||||
bne +
|
||||
dec $asmArrayvarname+$indexValue+1
|
||||
+ dec $asmArrayvarname+$indexValue""")
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
asmgen.out(" lda #<($asmArrayvarname+$indexValue) | ldy #>($asmArrayvarname+$indexValue)")
|
||||
asmgen.out(if(incr) " jsr floats.inc_var_f" else " jsr floats.dec_var_f")
|
||||
}
|
||||
else -> throw AssemblyError("need numeric type")
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
asmgen.loadScaledArrayIndexIntoRegister(targetArrayIdx, CpuRegister.X)
|
||||
when(elementDt) {
|
||||
in ByteDatatypes -> {
|
||||
asmgen.out(if (incr) " inc $asmArrayvarname,x" else " dec $asmArrayvarname,x")
|
||||
}
|
||||
in WordDatatypes -> {
|
||||
if(incr)
|
||||
asmgen.out(" inc $asmArrayvarname,x | bne + | inc $asmArrayvarname+1,x |+")
|
||||
else
|
||||
asmgen.out("""
|
||||
lda $asmArrayvarname,x
|
||||
bne +
|
||||
dec $asmArrayvarname+1,x
|
||||
+ dec $asmArrayvarname,x""")
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
asmgen.out("""
|
||||
ldy #>$asmArrayvarname
|
||||
clc
|
||||
adc #<$asmArrayvarname
|
||||
bcc +
|
||||
iny
|
||||
+ jsr floats.inc_var_f""")
|
||||
}
|
||||
else -> throw AssemblyError("weird array elt dt")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -241,7 +241,6 @@ class IRCodeGen(
|
|||
is PtWhen -> translate(node)
|
||||
is PtForLoop -> translate(node)
|
||||
is PtIfElse -> translate(node)
|
||||
is PtPostIncrDecr -> translate(node)
|
||||
is PtRepeatLoop -> translate(node)
|
||||
is PtLabel -> listOf(IRCodeChunk(node.name, null))
|
||||
is PtBreakpoint -> {
|
||||
|
@ -1431,164 +1430,6 @@ class IRCodeGen(
|
|||
}
|
||||
}
|
||||
|
||||
private fun translate(postIncrDecr: PtPostIncrDecr): IRCodeChunks {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val array = postIncrDecr.target.array
|
||||
if(array?.splitWords==true) {
|
||||
val variable = array.variable.name
|
||||
val fixedIndex = constIntValue(array.index)
|
||||
if(fixedIndex!=null) {
|
||||
val skipLabel = createLabelName()
|
||||
when(postIncrDecr.operator) {
|
||||
"++" -> {
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.INCM, IRDataType.BYTE, labelSymbol = "${variable}_lsb", symbolOffset = fixedIndex)
|
||||
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
|
||||
it += IRInstruction(Opcode.INCM, IRDataType.BYTE, labelSymbol = "${variable}_msb", symbolOffset = fixedIndex)
|
||||
}
|
||||
result += IRCodeChunk(skipLabel, null)
|
||||
}
|
||||
"--" -> {
|
||||
val valueReg=registers.nextFree()
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=valueReg, labelSymbol = "${variable}_lsb", symbolOffset = fixedIndex)
|
||||
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
|
||||
it += IRInstruction(Opcode.DECM, IRDataType.BYTE, labelSymbol = "${variable}_msb", symbolOffset = fixedIndex)
|
||||
}
|
||||
result += IRCodeChunk(skipLabel, null).also {
|
||||
it += IRInstruction(Opcode.DECM, IRDataType.BYTE, labelSymbol = "${variable}_lsb", symbolOffset = fixedIndex)
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird operator")
|
||||
}
|
||||
} else {
|
||||
val indexTr = expressionEval.translateExpression(array.index)
|
||||
addToResult(result, indexTr, indexTr.resultReg, -1)
|
||||
val incReg = registers.nextFree()
|
||||
val skipLabel = createLabelName()
|
||||
when(postIncrDecr.operator) {
|
||||
"++" -> {
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, labelSymbol = "${variable}_lsb")
|
||||
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=incReg)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, labelSymbol = "${variable}_lsb")
|
||||
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, labelSymbol = "${variable}_msb")
|
||||
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=incReg)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, labelSymbol = "${variable}_msb")
|
||||
}
|
||||
result += IRCodeChunk(skipLabel, null)
|
||||
}
|
||||
"--" -> {
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, labelSymbol = "${variable}_lsb")
|
||||
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, labelSymbol = "${variable}_msb")
|
||||
it += IRInstruction(Opcode.DEC, IRDataType.BYTE, reg1=incReg)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, labelSymbol = "${variable}_msb")
|
||||
}
|
||||
result += IRCodeChunk(skipLabel, null).also {
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, labelSymbol = "${variable}_lsb")
|
||||
it += IRInstruction(Opcode.DEC, IRDataType.BYTE, reg1=incReg)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, labelSymbol = "${variable}_lsb")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird operator")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val ident = postIncrDecr.target.identifier
|
||||
val memory = postIncrDecr.target.memory
|
||||
val irDt = irType(postIncrDecr.target.type)
|
||||
val operationMem: Opcode
|
||||
val operationRegister: Opcode
|
||||
when(postIncrDecr.operator) {
|
||||
"++" -> {
|
||||
operationMem = Opcode.INCM
|
||||
operationRegister = Opcode.INC
|
||||
}
|
||||
"--" -> {
|
||||
operationMem = Opcode.DECM
|
||||
operationRegister = Opcode.DEC
|
||||
}
|
||||
else -> throw AssemblyError("weird operator")
|
||||
}
|
||||
if(ident!=null) {
|
||||
addInstr(result, IRInstruction(operationMem, irDt, labelSymbol = ident.name), null)
|
||||
} else if(memory!=null) {
|
||||
val constAddress = memory.address as? PtNumber
|
||||
if(constAddress!=null) {
|
||||
addInstr(result, IRInstruction(operationMem, irDt, address = constAddress.number.toInt()), null)
|
||||
return result
|
||||
}
|
||||
val ptrWithOffset = memory.address as? PtBinaryExpression
|
||||
if(ptrWithOffset!=null && ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier) {
|
||||
if((ptrWithOffset.right as? PtNumber)?.number?.toInt() in 0..255) {
|
||||
// LOADIX only works with byte index.
|
||||
val ptrName = (ptrWithOffset.left as PtIdentifier).name
|
||||
val offsetReg = registers.nextFree()
|
||||
val incReg = registers.nextFree()
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=offsetReg, immediate = ptrWithOffset.right.asConstInteger())
|
||||
it += IRInstruction(Opcode.LOADIX, IRDataType.BYTE, reg1=incReg, reg2=offsetReg, labelSymbol = ptrName)
|
||||
it += IRInstruction(operationRegister, irDt, reg1 = incReg)
|
||||
it += IRInstruction(Opcode.STOREIX, IRDataType.BYTE, reg1=incReg, reg2=offsetReg, labelSymbol = ptrName)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
val offsetTypecast = ptrWithOffset?.right as? PtTypeCast
|
||||
if(ptrWithOffset!=null && ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier
|
||||
&& (ptrWithOffset.right.type in ByteDatatypes || offsetTypecast?.value?.type in ByteDatatypes)) {
|
||||
// LOADIX only works with byte index.
|
||||
val tr = if(offsetTypecast?.value?.type in ByteDatatypes)
|
||||
expressionEval.translateExpression(offsetTypecast!!.value)
|
||||
else
|
||||
expressionEval.translateExpression(ptrWithOffset.right)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val ptrName = (ptrWithOffset.left as PtIdentifier).name
|
||||
result += IRCodeChunk(null, null).also {
|
||||
val incReg = registers.nextFree()
|
||||
it += IRInstruction(Opcode.LOADIX, IRDataType.BYTE, reg1=incReg, reg2=tr.resultReg, labelSymbol = ptrName)
|
||||
it += IRInstruction(operationRegister, irDt, reg1 = incReg)
|
||||
it += IRInstruction(Opcode.STOREIX, IRDataType.BYTE, reg1=incReg, reg2=tr.resultReg, labelSymbol = ptrName)
|
||||
}
|
||||
return result
|
||||
}
|
||||
val tr = expressionEval.translateExpression(memory.address)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
val incReg = registers.nextFree()
|
||||
it += IRInstruction(Opcode.LOADI, irDt, reg1 = incReg, reg2 = tr.resultReg)
|
||||
it += IRInstruction(operationRegister, irDt, reg1 = incReg)
|
||||
it += IRInstruction(Opcode.STOREI, irDt, reg1 = incReg, reg2 = tr.resultReg)
|
||||
}
|
||||
return result
|
||||
} else if (array!=null) {
|
||||
val variable = array.variable.name
|
||||
val itemsize = program.memsizer.memorySize(array.type)
|
||||
val fixedIndex = constIntValue(array.index)
|
||||
if(fixedIndex!=null) {
|
||||
addInstr(result, IRInstruction(operationMem, irDt, labelSymbol = variable, symbolOffset = fixedIndex*itemsize), null)
|
||||
} else {
|
||||
val indexTr = expressionEval.translateExpression(array.index)
|
||||
addToResult(result, indexTr, indexTr.resultReg, -1)
|
||||
if(itemsize>1)
|
||||
result += multiplyByConst(IRDataType.BYTE, indexTr.resultReg, itemsize)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
val incReg = registers.nextFree()
|
||||
it += IRInstruction(Opcode.LOADX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
|
||||
it += IRInstruction(operationRegister, irDt, reg1=incReg)
|
||||
it += IRInstruction(Opcode.STOREX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
|
||||
}
|
||||
}
|
||||
} else
|
||||
throw AssemblyError("weird assigntarget")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun translate(repeat: PtRepeatLoop): IRCodeChunks {
|
||||
when (constIntValue(repeat.count)) {
|
||||
0 -> return emptyList()
|
||||
|
|
|
@ -107,18 +107,6 @@ class Inliner(private val program: Program, private val options: CompilationOpti
|
|||
inline
|
||||
}
|
||||
|
||||
is PostIncrDecr -> {
|
||||
if (stmt.target.identifier != null) {
|
||||
makeFullyScoped(stmt.target.identifier!!)
|
||||
true
|
||||
} else if (stmt.target.memoryAddress?.addressExpression is NumericLiteral || stmt.target.memoryAddress?.addressExpression is IdentifierReference) {
|
||||
if (stmt.target.memoryAddress?.addressExpression is IdentifierReference)
|
||||
makeFullyScoped(stmt.target.memoryAddress?.addressExpression as IdentifierReference)
|
||||
true
|
||||
} else
|
||||
false
|
||||
}
|
||||
|
||||
is Jump -> true
|
||||
else -> false
|
||||
}
|
||||
|
|
|
@ -5,9 +5,11 @@ import prog8.ast.expressions.*
|
|||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.*
|
||||
import prog8.code.core.AssociativeOperators
|
||||
import prog8.code.core.CompilationOptions
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.IErrorReporter
|
||||
import prog8.code.target.VMTarget
|
||||
import kotlin.math.floor
|
||||
|
||||
|
||||
class StatementOptimizer(private val program: Program,
|
||||
|
@ -185,13 +187,21 @@ class StatementOptimizer(private val program: Program,
|
|||
|
||||
val loopvarDt = forLoop.loopVarDt(program)
|
||||
if(loopvarDt.istype(DataType.UWORD) || loopvarDt.istype(DataType.UBYTE)) {
|
||||
|
||||
fun incOrDec(inc: Boolean): Assignment {
|
||||
val pos = forLoop.position
|
||||
val loopVar = forLoop.loopVar
|
||||
val addSubOne = BinaryExpression(loopVar.copy(), if(inc) "+" else "-", NumericLiteral.optimalInteger(1, pos), pos, false)
|
||||
return Assignment(AssignTarget(loopVar.copy(), null, null, pos), addSubOne, AssignmentOrigin.USERCODE, pos)
|
||||
}
|
||||
|
||||
if (range != null && range.from.constValue(program)?.number == 0.0 && range.step.constValue(program)?.number==1.0) {
|
||||
val toBinExpr = range.to as? BinaryExpression
|
||||
if(toBinExpr!=null && toBinExpr.operator=="-" && toBinExpr.right.constValue(program)?.number==1.0) {
|
||||
// FOR var IN 0 TO X-1 .... ---> var=0, DO {... , var++} UNTIL var==X
|
||||
val pos = forLoop.position
|
||||
val condition = BinaryExpression(forLoop.loopVar.copy(), "==", toBinExpr.left, pos)
|
||||
val incOne = PostIncrDecr(AssignTarget(forLoop.loopVar.copy(), null, null, pos), "++", pos)
|
||||
val incOne = incOrDec(true)
|
||||
forLoop.body.statements.add(incOne)
|
||||
val replacement = AnonymousScope(mutableListOf(
|
||||
Assignment(AssignTarget(forLoop.loopVar.copy(), null, null, pos),
|
||||
|
@ -208,7 +218,7 @@ class StatementOptimizer(private val program: Program,
|
|||
if (toConst == null) {
|
||||
// FOR var in 0 TO X ... ---> var=0, REPEAT { ... , IF var==X break , var++ }
|
||||
val pos = forLoop.position
|
||||
val incOne = PostIncrDecr(AssignTarget(forLoop.loopVar.copy(), null, null, pos), "++", pos)
|
||||
val incOne = incOrDec(true)
|
||||
val breakCondition = IfElse(
|
||||
BinaryExpression(forLoop.loopVar, "==", range.to, pos),
|
||||
AnonymousScope(mutableListOf(Break(pos)), pos),
|
||||
|
@ -235,7 +245,7 @@ class StatementOptimizer(private val program: Program,
|
|||
val pos = forLoop.position
|
||||
val checkValue = NumericLiteral(loopvarDt.getOr(DataType.UNDEFINED), if(loopvarDt.istype(DataType.UBYTE)) 255.0 else 65535.0, pos)
|
||||
val condition = BinaryExpression(forLoop.loopVar.copy(), "==", checkValue, pos)
|
||||
val decOne = PostIncrDecr(AssignTarget(forLoop.loopVar.copy(), null, null, pos), "--", pos)
|
||||
val decOne = incOrDec(false)
|
||||
forLoop.body.statements.add(decOne)
|
||||
val replacement = AnonymousScope(mutableListOf(
|
||||
Assignment(AssignTarget(forLoop.loopVar.copy(), null, null, pos),
|
||||
|
@ -390,35 +400,15 @@ class StatementOptimizer(private val program: Program,
|
|||
// assignments of the form: X = X <operator> <expr>
|
||||
// remove assignments that have no effect (such as X=X+0)
|
||||
// optimize/rewrite some other expressions
|
||||
val targetDt = targetIDt.getOr(DataType.UNDEFINED)
|
||||
val vardeclDt = (assignment.target.identifier?.targetVarDecl(program))?.type
|
||||
when (bexpr.operator) {
|
||||
"+" -> {
|
||||
if (rightCv == 0.0) {
|
||||
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
||||
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
|
||||
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..3.0 && options.compTarget.name!=VMTarget.NAME) {
|
||||
// replace by several INCs if it's not a memory address (inc on a memory mapped register doesn't work very well)
|
||||
val incs = AnonymousScope(mutableListOf(), assignment.position)
|
||||
repeat(rightCv.toInt()) {
|
||||
incs.statements.add(PostIncrDecr(assignment.target.copy(), "++", assignment.position))
|
||||
}
|
||||
return listOf(IAstModification.ReplaceNode(assignment, if(incs.statements.size==1) incs.statements[0] else incs, parent))
|
||||
}
|
||||
}
|
||||
}
|
||||
"-" -> {
|
||||
if (rightCv == 0.0) {
|
||||
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
||||
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
|
||||
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..3.0 && options.compTarget.name!=VMTarget.NAME) {
|
||||
// replace by several DECs if it's not a memory address (dec on a memory mapped register doesn't work very well)
|
||||
val decs = AnonymousScope(mutableListOf(), assignment.position)
|
||||
repeat(rightCv.toInt()) {
|
||||
decs.statements.add(PostIncrDecr(assignment.target.copy(), "--", assignment.position))
|
||||
}
|
||||
return listOf(IAstModification.ReplaceNode(assignment, decs, parent))
|
||||
}
|
||||
}
|
||||
}
|
||||
"*" -> if (rightCv == 1.0) return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
||||
|
|
|
@ -5,11 +5,11 @@ package prog8.buildversion
|
|||
*/
|
||||
const val MAVEN_GROUP = "prog8"
|
||||
const val MAVEN_NAME = "compiler"
|
||||
const val VERSION = "10.0"
|
||||
const val GIT_REVISION = -1
|
||||
const val GIT_SHA = "cc22861719e36ed842d00d6ca7c29792c2c37b9f"
|
||||
const val GIT_DATE = "2024-01-19T18:26:41Z"
|
||||
const val GIT_BRANCH = "master"
|
||||
const val BUILD_DATE = "2024-01-19T18:58:11Z"
|
||||
const val BUILD_UNIX_TIME = 1705690691084L
|
||||
const val VERSION = "10.1"
|
||||
const val GIT_REVISION = 4443
|
||||
const val GIT_SHA = "f87494207574000a25174fcf5db973885f49b1b9"
|
||||
const val GIT_DATE = "2024-02-04T15:22:43Z"
|
||||
const val GIT_BRANCH = "UNKNOWN"
|
||||
const val BUILD_DATE = "2024-02-06T17:41:04Z"
|
||||
const val BUILD_UNIX_TIME = 1707241264826L
|
||||
const val DIRTY = 1
|
||||
|
|
|
@ -92,7 +92,7 @@ internal class AstChecker(private val program: Program,
|
|||
if (iterations < 0 || iterations > 65535)
|
||||
errors.err("invalid number of unrolls", unrollLoop.position)
|
||||
unrollLoop.body.statements.forEach {
|
||||
if (it !is InlineAssembly && it !is Assignment && it !is BuiltinFunctionCallStatement && it !is FunctionCallStatement && it !is PostIncrDecr)
|
||||
if (it !is InlineAssembly && it !is Assignment && it !is BuiltinFunctionCallStatement && it !is FunctionCallStatement)
|
||||
errors.err("invalid statement in unroll loop", it.position)
|
||||
}
|
||||
if (iterations * unrollLoop.body.statements.size > 256) {
|
||||
|
@ -1329,41 +1329,6 @@ internal class AstChecker(private val program: Program,
|
|||
}
|
||||
}
|
||||
|
||||
override fun visit(postIncrDecr: PostIncrDecr) {
|
||||
if(postIncrDecr.target.identifier != null) {
|
||||
val targetName = postIncrDecr.target.identifier!!.nameInSource
|
||||
val target = postIncrDecr.definingScope.lookup(targetName)
|
||||
if(target==null) {
|
||||
val symbol = postIncrDecr.target.identifier!!
|
||||
errors.undefined(symbol.nameInSource, symbol.position)
|
||||
} else {
|
||||
if(target !is VarDecl || target.type== VarDeclType.CONST) {
|
||||
errors.err("can only increment or decrement a variable", postIncrDecr.position)
|
||||
} else if(target.datatype !in NumericDatatypes) {
|
||||
errors.err("cannot increment/decrement this", postIncrDecr.position)
|
||||
}
|
||||
}
|
||||
} else if(postIncrDecr.target.arrayindexed != null) {
|
||||
val indexed = postIncrDecr.target.arrayindexed!!
|
||||
val target = indexed.arrayvar.targetStatement(program)
|
||||
if(target==null) {
|
||||
errors.undefined(indexed.arrayvar.nameInSource, indexed.arrayvar.position)
|
||||
}
|
||||
else {
|
||||
val dt = (target as VarDecl).datatype
|
||||
if(dt !in NumericDatatypes && dt !in ArrayDatatypes && dt!=DataType.STR)
|
||||
errors.err("cannot increment/decrement this", postIncrDecr.position)
|
||||
}
|
||||
}
|
||||
// else if(postIncrDecr.target.memoryAddress != null) { } // a memory location can always be ++/--
|
||||
|
||||
if(postIncrDecr.target.inferType(program) istype DataType.BOOL) {
|
||||
errors.err("can't use boolean operand with this operator ${postIncrDecr.operator}", postIncrDecr.position)
|
||||
}
|
||||
|
||||
super.visit(postIncrDecr)
|
||||
}
|
||||
|
||||
override fun visit(arrayIndexedExpression: ArrayIndexedExpression) {
|
||||
checkLongType(arrayIndexedExpression)
|
||||
val target = arrayIndexedExpression.arrayvar.targetStatement(program)
|
||||
|
|
|
@ -52,7 +52,6 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr
|
|||
is InlineAssembly -> transform(statement)
|
||||
is Jump -> transform(statement)
|
||||
is Label -> transform(statement)
|
||||
is PostIncrDecr -> transform(statement)
|
||||
is RepeatLoop -> transform(statement)
|
||||
is UnrollLoop -> transform(statement)
|
||||
is Return -> transform(statement)
|
||||
|
@ -397,12 +396,6 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr
|
|||
private fun transform(label: Label): PtLabel =
|
||||
PtLabel(label.name, label.position)
|
||||
|
||||
private fun transform(src: PostIncrDecr): PtPostIncrDecr {
|
||||
val post = PtPostIncrDecr(src.operator, src.position)
|
||||
post.add(transform(src.target))
|
||||
return post
|
||||
}
|
||||
|
||||
private fun transform(srcRepeat: RepeatLoop): PtRepeatLoop {
|
||||
if(srcRepeat.iterations==null)
|
||||
throw FatalAstException("repeat-forever loop should have been replaced with label+jump")
|
||||
|
|
|
@ -149,12 +149,6 @@ internal class ParentNodeChecker: AstWalker() {
|
|||
return noModifications
|
||||
}
|
||||
|
||||
override fun before(postIncrDecr: PostIncrDecr, parent: Node): Iterable<IAstModification> {
|
||||
if(postIncrDecr.parent!==parent)
|
||||
throw FatalAstException("parent node mismatch at $postIncrDecr")
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun before(range: RangeExpression, parent: Node): Iterable<IAstModification> {
|
||||
if(range.parent!==parent)
|
||||
throw FatalAstException("parent node mismatch at $range")
|
||||
|
|
|
@ -225,7 +225,7 @@ class TestOptimization: FunSpec({
|
|||
uword yy ; to be removed
|
||||
yy=99 ; to be removed
|
||||
cx16.r0 = 0
|
||||
cx16.r0++
|
||||
rol(cx16.r0)
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
|
|
@ -39,7 +39,7 @@ class TestScoping: FunSpec({
|
|||
sub start() {
|
||||
repeat 10 {
|
||||
ubyte xx = 99
|
||||
xx++
|
||||
rol(xx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ class TestScoping: FunSpec({
|
|||
withClue("vardecl in repeat should be replaced by init assignment") {
|
||||
(initassign?.value as? NumericLiteral)?.number?.toInt() shouldBe 99
|
||||
}
|
||||
repeatbody.statements[1] shouldBe instanceOf<PostIncrDecr>()
|
||||
repeatbody.statements[1] shouldBe instanceOf<FunctionCallStatement>()
|
||||
}
|
||||
|
||||
test("labels with anon scopes") {
|
||||
|
|
|
@ -8,7 +8,10 @@ import prog8.ast.expressions.AddressOf
|
|||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.expressions.PrefixExpression
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.statements.Block
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.core.SourceCode
|
||||
import prog8.parser.Prog8Parser
|
||||
|
@ -56,7 +59,7 @@ class TestIdentifierRef: FunSpec({
|
|||
program.addModule(module)
|
||||
val mstmts = (module.statements.single() as Block).statements
|
||||
val stmts = mstmts.filterIsInstance<Subroutine>().single().statements
|
||||
val wwref = (stmts[0] as PostIncrDecr).target.identifier!!
|
||||
val wwref = (stmts[0] as Assignment).target.identifier!!
|
||||
val mainref = ((stmts[1] as Assignment).value as AddressOf).identifier
|
||||
wwref.nameInSource shouldBe listOf("ww")
|
||||
wwref.wasStringLiteral(program) shouldBe false
|
||||
|
|
|
@ -653,7 +653,7 @@ class TestProg8Parser: FunSpec( {
|
|||
sub start() {
|
||||
repeat {
|
||||
ubyte xx = 99
|
||||
xx++
|
||||
rol(xx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -673,7 +673,7 @@ class TestProg8Parser: FunSpec( {
|
|||
}
|
||||
val initvalue = (repeatbody.statements[0] as VarDecl).value as? NumericLiteral
|
||||
initvalue?.number?.toInt() shouldBe 99
|
||||
repeatbody.statements[1] shouldBe instanceOf<PostIncrDecr>()
|
||||
repeatbody.statements[1] shouldBe instanceOf<FunctionCallStatement>()
|
||||
// the ast processing steps used in the compiler, will eventually move the var up to the containing scope (subroutine).
|
||||
}
|
||||
|
||||
|
|
|
@ -358,11 +358,6 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
|
|||
chainedAssignment.nested.accept(this)
|
||||
}
|
||||
|
||||
override fun visit(postIncrDecr: PostIncrDecr) {
|
||||
postIncrDecr.target.accept(this)
|
||||
output(postIncrDecr.operator)
|
||||
}
|
||||
|
||||
override fun visit(breakStmt: Break) {
|
||||
output("break")
|
||||
}
|
||||
|
|
|
@ -93,7 +93,13 @@ private fun StatementContext.toAst() : Statement {
|
|||
if(augassign!=null) return augassign
|
||||
|
||||
postincrdecr()?.let {
|
||||
return PostIncrDecr(it.assign_target().toAst(), it.operator.text, it.toPosition())
|
||||
val tgt = it.assign_target().toAst()
|
||||
val operator = it.operator.text
|
||||
val pos = it.toPosition()
|
||||
print("\u001b[92mINFO\u001B[0m ") // bright green
|
||||
println("${pos}: ++ and -- will be removed in a future version, please use +=1 or -=1 instead.")
|
||||
val addSubOne = BinaryExpression(tgt.toExpression(), if(operator=="++") "+" else "-", NumericLiteral.optimalInteger(1, pos), pos, false)
|
||||
return Assignment(tgt, addSubOne, AssignmentOrigin.USERCODE, pos)
|
||||
}
|
||||
|
||||
val directive = directive()?.toAst()
|
||||
|
|
|
@ -630,27 +630,6 @@ data class AssignTarget(var identifier: IdentifierReference?,
|
|||
|
||||
}
|
||||
|
||||
class PostIncrDecr(var target: AssignTarget, val operator: String, override val position: Position) : Statement() {
|
||||
override lateinit var parent: Node
|
||||
|
||||
override fun linkParents(parent: Node) {
|
||||
this.parent = parent
|
||||
target.linkParents(this)
|
||||
}
|
||||
|
||||
override fun replaceChildNode(node: Node, replacement: Node) {
|
||||
require(replacement is AssignTarget && node===target)
|
||||
target = replacement
|
||||
replacement.parent = this
|
||||
}
|
||||
|
||||
override fun referencesIdentifier(nameInSource: List<String>): Boolean = target.referencesIdentifier(nameInSource)
|
||||
override fun copy() = PostIncrDecr(target.copy(), operator, position)
|
||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
||||
override fun toString() = "PostIncrDecr(op: $operator, target: $target, pos=$position)"
|
||||
}
|
||||
|
||||
class Jump(var address: UInt?,
|
||||
val identifier: IdentifierReference?,
|
||||
val generatedLabel: String?, // can be used in code generation scenarios
|
||||
|
|
|
@ -122,7 +122,6 @@ abstract class AstWalker {
|
|||
open fun before(memwrite: DirectMemoryWrite, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(module: Module, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(numLiteral: NumericLiteral, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(postIncrDecr: PostIncrDecr, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(program: Program): Iterable<IAstModification> = noModifications
|
||||
open fun before(range: RangeExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(untilLoop: UntilLoop, parent: Node): Iterable<IAstModification> = noModifications
|
||||
|
@ -167,7 +166,6 @@ abstract class AstWalker {
|
|||
open fun after(memwrite: DirectMemoryWrite, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(module: Module, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(numLiteral: NumericLiteral, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(postIncrDecr: PostIncrDecr, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(program: Program): Iterable<IAstModification> = noModifications
|
||||
open fun after(range: RangeExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(untilLoop: UntilLoop, parent: Node): Iterable<IAstModification> = noModifications
|
||||
|
@ -367,12 +365,6 @@ abstract class AstWalker {
|
|||
track(after(assignment, parent), assignment, parent)
|
||||
}
|
||||
|
||||
fun visit(postIncrDecr: PostIncrDecr, parent: Node) {
|
||||
track(before(postIncrDecr, parent), postIncrDecr, parent)
|
||||
postIncrDecr.target.accept(this, postIncrDecr)
|
||||
track(after(postIncrDecr, parent), postIncrDecr, parent)
|
||||
}
|
||||
|
||||
fun visit(breakStmt: Break, parent: Node) {
|
||||
track(before(breakStmt, parent), breakStmt, parent)
|
||||
track(after(breakStmt, parent), breakStmt, parent)
|
||||
|
|
|
@ -108,10 +108,6 @@ interface IAstVisitor {
|
|||
assignment.value.accept(this)
|
||||
}
|
||||
|
||||
fun visit(postIncrDecr: PostIncrDecr) {
|
||||
postIncrDecr.target.accept(this)
|
||||
}
|
||||
|
||||
fun visit(breakStmt: Break) {
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
TODO
|
||||
====
|
||||
|
||||
- remove ++/-- (just use Pythonesque x+=1): optimize codegen for +=1/-=1
|
||||
- eventually remove ++/-- from the parser? Or keep it?
|
||||
|
||||
|
||||
(after merge in boolean): move all "OperatorXinplace" from expressionGen to AssignmentGen, see if we can get rid of the Result return type.
|
||||
|
||||
...
|
||||
|
@ -80,7 +84,6 @@ What if we were to re-introduce Structs in prog8? Some thoughts:
|
|||
Other language/syntax features to think about
|
||||
---------------------------------------------
|
||||
|
||||
- remove ++/-- (just use Pythonesque x+=1) OR make ++/-- into a postfix expression (but then we need a prefix variant of them too?) maybe via a new builtin function like postincr__w() etc?
|
||||
- support for assigning multiple return values from romsub/asmsub to multiple variables.
|
||||
- add (rom/ram)bank support to romsub. A call will then automatically switch banks, use callfar and something else when in banked ram.
|
||||
challenges: how to not make this too X16 specific? How does the compiler know what bank to switch (ram/rom)?
|
||||
|
|
113
examples/test.p8
113
examples/test.p8
|
@ -1,115 +1,18 @@
|
|||
%import textio
|
||||
%import floats
|
||||
%import math
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
; ubyte[10] az
|
||||
ubyte @shared offset=4
|
||||
uword @shared az = $4000
|
||||
ubyte @shared value = 22
|
||||
ubyte @shared xx
|
||||
ubyte @shared yy
|
||||
|
||||
az[20] |= 99
|
||||
az[21] &= 99
|
||||
az[22] ^= 99
|
||||
az[23] += 99
|
||||
az[24] -= 99
|
||||
; az[2000] |= 99
|
||||
; az[value] |= 99
|
||||
; az[cx16.r0] |= 99
|
||||
xx++
|
||||
yy++
|
||||
xx--
|
||||
yy--
|
||||
|
||||
; cx16.r0L = az[200]
|
||||
; cx16.r1L = az[2000]
|
||||
; cx16.r0L = az[value]
|
||||
; cx16.r0H = value*4 + az[value]
|
||||
; cx16.r0L = az[value] + value*4
|
||||
;
|
||||
; @($4004) = 99
|
||||
; az[4]--
|
||||
; @(az + offset)--
|
||||
; txt.print_ub(@($4004))
|
||||
; txt.nl()
|
||||
; az[4]++
|
||||
; @(az+offset)++
|
||||
; txt.print_ub(@($4004))
|
||||
; txt.nl()
|
||||
; cx16.r0L = az[4] + value*5
|
||||
; cx16.r1L = value*5 + az[4]
|
||||
|
||||
|
||||
; ubyte @shared xx
|
||||
; ubyte[3] ubarr
|
||||
; uword[3] @split uwarr
|
||||
; byte[3] sbarr
|
||||
; bool[3] barr
|
||||
; float[3] flarr
|
||||
; bool @shared bb
|
||||
; uword ptr = &ubarr
|
||||
;
|
||||
; ptr[1]++
|
||||
; ptr[1]++
|
||||
; ptr[1]--
|
||||
; txt.print_ub(ubarr[1])
|
||||
; txt.nl()
|
||||
; ptr[1]+=4
|
||||
; ptr[1]-=3
|
||||
; txt.print_ub(ubarr[1])
|
||||
; txt.nl()
|
||||
|
||||
; sbarr[1] = sbarr[1] == 0
|
||||
; sbarr[1] = sbarr[1] != 0
|
||||
; sbarr[1] = sbarr[1] < 0
|
||||
; sbarr[1] = sbarr[1] <= 0
|
||||
; sbarr[1] = sbarr[1] > 0
|
||||
; sbarr[1] = sbarr[1] >= 0
|
||||
;
|
||||
; xx = 1
|
||||
;
|
||||
; sbarr[xx] = sbarr[xx] == 0
|
||||
; sbarr[xx] = sbarr[xx] != 0
|
||||
; sbarr[xx] = sbarr[xx] < 0
|
||||
; sbarr[xx] = sbarr[xx] <= 0
|
||||
; sbarr[xx] = sbarr[xx] > 0
|
||||
; sbarr[xx] = sbarr[xx] >= 0
|
||||
|
||||
; sbarr[1] = sbarr[1] == 2
|
||||
; sbarr[1] = sbarr[1] != 2
|
||||
; sbarr[1] = sbarr[1] < 2
|
||||
; sbarr[1] = sbarr[1] <= 2
|
||||
; sbarr[1] = sbarr[1] > 2
|
||||
; sbarr[1] = sbarr[1] >= 2
|
||||
; xx = 1
|
||||
; sbarr[xx] = sbarr[xx] == 2
|
||||
; sbarr[xx] = sbarr[xx] != 2
|
||||
; sbarr[xx] = sbarr[xx] < 2
|
||||
; sbarr[xx] = sbarr[xx] <= 2
|
||||
; sbarr[xx] = sbarr[xx] > 2
|
||||
; sbarr[xx] = sbarr[xx] >= 2
|
||||
|
||||
; ubarr[1] = ubarr[1] == 2
|
||||
; ubarr[1] = ubarr[1] < 2
|
||||
; ubarr[1] = ubarr[1] <= 2
|
||||
; ubarr[1] = ubarr[1] > 3
|
||||
; ubarr[1] = ubarr[1] >= 3
|
||||
|
||||
; barr[1] = barr[0] and barr[2]
|
||||
; barr[1] = barr[0] or barr[2]
|
||||
; barr[1] = barr[0] xor barr[2]
|
||||
; barr[1] = not barr[0]
|
||||
;
|
||||
; ubarr[1] = 999
|
||||
; ubarr[1] = ubarr[1]==999
|
||||
; txt.print_uw(ubarr[1])
|
||||
;
|
||||
; barr[1] = barr[1] and bb
|
||||
; barr[1] = barr[1] or bb
|
||||
; barr[1] = barr[1] xor bb
|
||||
;
|
||||
; bb = bb and barr[1]
|
||||
; bb = bb or barr[1]
|
||||
; bb = bb xor barr[1]
|
||||
; bb = not bb
|
||||
xx+=1
|
||||
yy-=1
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user