mirror of
https://github.com/irmen/prog8.git
synced 2024-12-27 05:29:38 +00:00
created direct-on-memory ++/-- and augmented assignemnts.
This commit is contained in:
parent
aeb963673a
commit
c07bd8a4a8
@ -4,11 +4,22 @@
|
||||
|
||||
sub start() {
|
||||
|
||||
ubyte[63] balloonsprite = [ 0,127,0,1,255,192,3,255,224,3,231,224,
|
||||
7,217,240,7,223,240,7,217,240,3,231,224,
|
||||
3,255,224,3,255,224,2,255,160,1,127,64,
|
||||
1,62,64,0,156,128,0,156,128,0,73,0,0,73,0,
|
||||
0,62,0,0,62,0,0,62,0,0,28,0 ]
|
||||
A+=5
|
||||
|
||||
; @todo if-else if should compile ?:
|
||||
; if A>100
|
||||
; Y=2
|
||||
; else if A>20
|
||||
; Y=3
|
||||
|
||||
|
||||
; @($d020) = 5
|
||||
@($d020)++
|
||||
@($d021)--
|
||||
; @($d020)=(@$d020)+5
|
||||
@($d020)+=5
|
||||
; @($d021)=(@$d021)-5
|
||||
@($d021)-=5
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -391,7 +391,6 @@ class AstChecker(private val namespace: INameScope,
|
||||
if(memAddr!=null) {
|
||||
if(memAddr<0 || memAddr>=65536)
|
||||
checkResult.add(ExpressionError("address out of range", target.position))
|
||||
return assignment
|
||||
}
|
||||
|
||||
if(target.identifier!=null) {
|
||||
@ -433,9 +432,19 @@ class AstChecker(private val namespace: INameScope,
|
||||
// A /= 3 -> check as if it was A = A / 3
|
||||
val newTarget: IExpression =
|
||||
when {
|
||||
target.register!=null -> RegisterExpr(target.register, target.position)
|
||||
target.identifier!=null -> target.identifier
|
||||
target.arrayindexed!=null -> target.arrayindexed
|
||||
target.register != null -> RegisterExpr(target.register, target.position)
|
||||
target.identifier != null -> target.identifier
|
||||
target.arrayindexed != null -> target.arrayindexed
|
||||
target.memAddressExpression != null -> {
|
||||
// @addr += 4 --> @addr = @addr +4
|
||||
// TODO: make it so that it follows the others
|
||||
val memRead = DirectMemoryExpression(target.memAddressExpression!!, target.position)
|
||||
val expression = BinaryExpression(memRead, assignment.aug_op.substringBeforeLast('='), assignment.value, assignment.position)
|
||||
expression.linkParents(assignment.parent)
|
||||
val assignment2 = Assignment(listOf(target), null, expression, assignment.position)
|
||||
assignment2.linkParents(assignment.parent)
|
||||
return assignment2
|
||||
}
|
||||
else -> throw FatalAstException("strange assignment")
|
||||
}
|
||||
|
||||
@ -796,7 +805,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
|
||||
override fun process(postIncrDecr: PostIncrDecr): IStatement {
|
||||
if(postIncrDecr.target.identifier!=null) {
|
||||
if(postIncrDecr.target.identifier != null) {
|
||||
val targetName = postIncrDecr.target.identifier!!.nameInSource
|
||||
val target = namespace.lookup(targetName, postIncrDecr)
|
||||
if(target==null) {
|
||||
@ -808,7 +817,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
checkResult.add(SyntaxError("can only increment or decrement a byte/float/word variable", postIncrDecr.position))
|
||||
}
|
||||
}
|
||||
} else if(postIncrDecr.target.arrayindexed!=null) {
|
||||
} else if(postIncrDecr.target.arrayindexed != null) {
|
||||
val target = postIncrDecr.target.arrayindexed?.identifier?.targetStatement(namespace)
|
||||
if(target==null) {
|
||||
checkResult.add(SyntaxError("undefined symbol", postIncrDecr.position))
|
||||
@ -818,6 +827,8 @@ class AstChecker(private val namespace: INameScope,
|
||||
if(dt !in NumericDatatypes && dt !in ArrayDatatypes)
|
||||
checkResult.add(SyntaxError("can only increment or decrement a byte/float/word", postIncrDecr.position))
|
||||
}
|
||||
} else if(postIncrDecr.target.memAddressExpression != null) {
|
||||
// a memory location can always be ++/--
|
||||
}
|
||||
return super.process(postIncrDecr)
|
||||
}
|
||||
|
@ -1254,18 +1254,18 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
private fun translate(stmt: PostIncrDecr) {
|
||||
prog.line(stmt.position)
|
||||
when {
|
||||
stmt.target.register!=null -> when(stmt.operator) {
|
||||
stmt.target.register != null -> when(stmt.operator) {
|
||||
"++" -> prog.instr(Opcode.INC_VAR_UB, callLabel = stmt.target.register.toString())
|
||||
"--" -> prog.instr(Opcode.DEC_VAR_UB, callLabel = stmt.target.register.toString())
|
||||
}
|
||||
stmt.target.identifier!=null -> {
|
||||
stmt.target.identifier != null -> {
|
||||
val targetStatement = stmt.target.identifier!!.targetStatement(namespace) as VarDecl
|
||||
when(stmt.operator) {
|
||||
"++" -> prog.instr(opcodeIncvar(targetStatement.datatype), callLabel = targetStatement.scopedname)
|
||||
"--" -> prog.instr(opcodeDecvar(targetStatement.datatype), callLabel = targetStatement.scopedname)
|
||||
}
|
||||
}
|
||||
stmt.target.arrayindexed!=null -> {
|
||||
stmt.target.arrayindexed != null -> {
|
||||
val variable = stmt.target.arrayindexed!!.identifier?.targetStatement(namespace) as VarDecl
|
||||
translate(stmt.target.arrayindexed!!.arrayspec.x)
|
||||
when(stmt.operator) {
|
||||
@ -1273,7 +1273,18 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
"--" -> prog.instr(opcodeDecArrayindexedVar(variable.datatype), callLabel = variable.scopedname)
|
||||
}
|
||||
}
|
||||
else -> throw CompilerException("very strange postincrdecr")
|
||||
stmt.target.memAddressExpression != null -> {
|
||||
val address = stmt.target.memAddressExpression!!.constValue(namespace, heap)?.asIntegerValue
|
||||
if(address!=null) {
|
||||
when(stmt.operator) {
|
||||
"++" -> prog.instr(Opcode.INC_MEMORY, Value(DataType.UWORD, address))
|
||||
"--" -> prog.instr(Opcode.DEC_MEMORY, Value(DataType.UWORD, address))
|
||||
}
|
||||
} else {
|
||||
TODO("memory ++/-- ${stmt.target.memAddressExpression}")
|
||||
}
|
||||
}
|
||||
else -> throw CompilerException("very strange postincrdecr ${stmt.target}")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1345,7 +1356,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
if(stmt.aug_op!=null) {
|
||||
// augmented assignment
|
||||
when {
|
||||
assignTarget.identifier!=null -> {
|
||||
assignTarget.identifier != null -> {
|
||||
val target = assignTarget.identifier.targetStatement(namespace)!!
|
||||
when(target) {
|
||||
is VarDecl -> {
|
||||
@ -1355,8 +1366,11 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
else -> throw CompilerException("invalid assignment target type ${target::class}")
|
||||
}
|
||||
}
|
||||
assignTarget.register!=null -> prog.instr(Opcode.PUSH_VAR_BYTE, callLabel = assignTarget.register.toString())
|
||||
assignTarget.arrayindexed!=null -> translate(assignTarget.arrayindexed, false)
|
||||
assignTarget.register != null -> prog.instr(Opcode.PUSH_VAR_BYTE, callLabel = assignTarget.register.toString())
|
||||
assignTarget.arrayindexed != null -> translate(assignTarget.arrayindexed, false)
|
||||
assignTarget.memAddressExpression != null -> {
|
||||
TODO("translate aug assign on memory address $stmt")
|
||||
}
|
||||
}
|
||||
|
||||
translateAugAssignOperator(stmt.aug_op, stmt.value.resultingDatatype(namespace, heap))
|
||||
@ -1496,7 +1510,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateAugAssignOperator(aug_op: String, valueDt: DataType?) {
|
||||
private fun translateAugAssignOperator(aug_op: String, valueDt: DataType?) { // @todo: not used in practice? (all augassigns are converted to normal assigns)
|
||||
if(valueDt==null)
|
||||
throw CompilerException("value datatype not known")
|
||||
val validDt = setOf(DataType.UBYTE, DataType.UWORD, DataType.FLOAT)
|
||||
|
@ -164,6 +164,8 @@ enum class Opcode {
|
||||
DEC_VAR_W,
|
||||
DEC_VAR_UW,
|
||||
DEC_VAR_F,
|
||||
INC_MEMORY,
|
||||
DEC_MEMORY,
|
||||
|
||||
// comparisons
|
||||
// @todo the comparisons push the result back on the stack. Optimize this to work with just processor flags? This does mean you can no longer use a logical boolean result as a byte 0/1 value ?
|
||||
|
@ -655,6 +655,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
jsr prog8_lib.dec_var_f
|
||||
"""
|
||||
}
|
||||
Opcode.INC_MEMORY -> " inc ${hexVal(ins)}"
|
||||
Opcode.DEC_MEMORY -> " dec ${hexVal(ins)}"
|
||||
Opcode.NEG_B -> " jsr prog8_lib.neg_b"
|
||||
Opcode.NEG_W -> " jsr prog8_lib.neg_w"
|
||||
Opcode.NEG_F -> " jsr prog8_lib.neg_f"
|
||||
|
@ -968,6 +968,16 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
val array = heap.get(variable.heapId)
|
||||
array.array!![index].dec()
|
||||
}
|
||||
Opcode.INC_MEMORY -> {
|
||||
val address = evalstack.pop()
|
||||
checkDt(address, DataType.UWORD)
|
||||
TODO("inc_memory $address")
|
||||
}
|
||||
Opcode.DEC_MEMORY -> {
|
||||
val address = evalstack.pop()
|
||||
checkDt(address, DataType.UWORD)
|
||||
TODO("dec_memory $address")
|
||||
}
|
||||
Opcode.MSB -> {
|
||||
val v = evalstack.pop()
|
||||
checkDt(v, DataType.UWORD, DataType.WORD)
|
||||
|
Loading…
Reference in New Issue
Block a user