created direct-on-memory ++/-- and augmented assignemnts.

This commit is contained in:
Irmen de Jong 2018-12-31 02:25:45 +01:00
parent aeb963673a
commit c07bd8a4a8
6 changed files with 69 additions and 19 deletions

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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 ?

View File

@ -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"

View File

@ -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)