mirror of
https://github.com/irmen/prog8.git
synced 2025-01-03 06:29:54 +00:00
new attempt
This commit is contained in:
parent
0c81b32cac
commit
f28206d989
@ -180,7 +180,13 @@ class PtFunctionCall(val name: String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtIdentifier(val name: String, type: DataType, position: Position) : PtExpression(type, position)
|
class PtIdentifier(val name: String, type: DataType, position: Position) : PtExpression(type, position) {
|
||||||
|
override fun toString(): String {
|
||||||
|
return "[PtIdentifier:$name $type $position]"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copy() = PtIdentifier(name, type, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtMemoryByte(position: Position) : PtExpression(DataType.UBYTE, position) {
|
class PtMemoryByte(position: Position) : PtExpression(DataType.UBYTE, position) {
|
||||||
|
@ -38,20 +38,17 @@ class PtSub(
|
|||||||
class PtSubroutineParameter(name: String, val type: DataType, position: Position): PtNamedNode(name, position)
|
class PtSubroutineParameter(name: String, val type: DataType, position: Position): PtNamedNode(name, position)
|
||||||
|
|
||||||
|
|
||||||
class PtAssignment(position: Position) : PtNode(position) {
|
sealed interface IPtAssignment {
|
||||||
|
val children: MutableList<PtNode>
|
||||||
val target: PtAssignTarget
|
val target: PtAssignTarget
|
||||||
get() = children[0] as PtAssignTarget
|
get() = children[0] as PtAssignTarget
|
||||||
val value: PtExpression
|
val value: PtExpression
|
||||||
get() = children[1] as PtExpression
|
get() = children[1] as PtExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PtAssignment(position: Position) : PtNode(position), IPtAssignment
|
||||||
|
|
||||||
class PtAugmentedAssign(val operator: String, position: Position) : PtNode(position) {
|
class PtAugmentedAssign(val operator: String, position: Position) : PtNode(position), IPtAssignment
|
||||||
val target: PtAssignTarget
|
|
||||||
get() = children[0] as PtAssignTarget
|
|
||||||
val value: PtExpression
|
|
||||||
get() = children[1] as PtExpression
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class PtAssignTarget(position: Position) : PtNode(position) {
|
class PtAssignTarget(position: Position) : PtNode(position) {
|
||||||
@ -95,7 +92,7 @@ class PtForLoop(position: Position) : PtNode(position) {
|
|||||||
|
|
||||||
|
|
||||||
class PtIfElse(position: Position) : PtNode(position) {
|
class PtIfElse(position: Position) : PtNode(position) {
|
||||||
val condition: PtExpression // either PtRpn or PtBinaryExpression
|
val condition: PtExpression
|
||||||
get() = children[0] as PtExpression
|
get() = children[0] as PtExpression
|
||||||
val ifScope: PtNodeGroup
|
val ifScope: PtNodeGroup
|
||||||
get() = children[1] as PtNodeGroup
|
get() = children[1] as PtNodeGroup
|
||||||
|
@ -21,13 +21,6 @@ class AsmGen6502: ICodeGeneratorBackend {
|
|||||||
options: CompilationOptions,
|
options: CompilationOptions,
|
||||||
errors: IErrorReporter
|
errors: IErrorReporter
|
||||||
): IAssemblyProgram? {
|
): IAssemblyProgram? {
|
||||||
if(options.useNewExprCode) {
|
|
||||||
// TODO("transform BinExprs?")
|
|
||||||
// errors.warn("EXPERIMENTAL NEW EXPRESSION CODEGEN IS USED. CODE SIZE+SPEED POSSIBLY SUFFERS.", Position.DUMMY)
|
|
||||||
}
|
|
||||||
|
|
||||||
// printAst(program, true) { println(it) }
|
|
||||||
|
|
||||||
val asmgen = AsmGen6502Internal(program, symbolTable, options, errors)
|
val asmgen = AsmGen6502Internal(program, symbolTable, options, errors)
|
||||||
return asmgen.compileToAssembly()
|
return asmgen.compileToAssembly()
|
||||||
}
|
}
|
||||||
@ -551,28 +544,74 @@ class AsmGen6502Internal (
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: PtIfElse) {
|
private fun translate(stmt: PtIfElse) {
|
||||||
val condition = stmt.condition as PtBinaryExpression
|
val condition = stmt.condition as? PtBinaryExpression
|
||||||
requireComparisonExpression(condition) // IfStatement: condition must be of form 'x <comparison> <value>'
|
if(condition!=null) {
|
||||||
if (stmt.elseScope.children.isEmpty()) {
|
require(!options.useNewExprCode)
|
||||||
val jump = stmt.ifScope.children.singleOrNull()
|
requireComparisonExpression(condition) // IfStatement: condition must be of form 'x <comparison> <value>'
|
||||||
if (jump is PtJump) {
|
if (stmt.elseScope.children.isEmpty()) {
|
||||||
translateCompareAndJumpIfTrue(condition, jump)
|
val jump = stmt.ifScope.children.singleOrNull()
|
||||||
|
if (jump is PtJump) {
|
||||||
|
translateCompareAndJumpIfTrue(condition, jump)
|
||||||
|
} else {
|
||||||
|
val endLabel = makeLabel("if_end")
|
||||||
|
translateCompareAndJumpIfFalse(condition, endLabel)
|
||||||
|
translate(stmt.ifScope)
|
||||||
|
out(endLabel)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// both true and else parts
|
||||||
|
val elseLabel = makeLabel("if_else")
|
||||||
val endLabel = makeLabel("if_end")
|
val endLabel = makeLabel("if_end")
|
||||||
translateCompareAndJumpIfFalse(condition, endLabel)
|
translateCompareAndJumpIfFalse(condition, elseLabel)
|
||||||
translate(stmt.ifScope)
|
translate(stmt.ifScope)
|
||||||
|
jmp(endLabel)
|
||||||
|
out(elseLabel)
|
||||||
|
translate(stmt.elseScope)
|
||||||
out(endLabel)
|
out(endLabel)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// both true and else parts
|
// condition is a simple expression "if X" --> "if X!=0"
|
||||||
val elseLabel = makeLabel("if_else")
|
val zero = PtNumber(DataType.UBYTE,0.0, stmt.position)
|
||||||
val endLabel = makeLabel("if_end")
|
val leftConst = stmt.condition as? PtNumber
|
||||||
translateCompareAndJumpIfFalse(condition, elseLabel)
|
if (stmt.elseScope.children.isEmpty()) {
|
||||||
translate(stmt.ifScope)
|
val jump = stmt.ifScope.children.singleOrNull()
|
||||||
jmp(endLabel)
|
if (jump is PtJump) {
|
||||||
out(elseLabel)
|
val label = when {
|
||||||
translate(stmt.elseScope)
|
jump.generatedLabel!=null -> jump.generatedLabel!!
|
||||||
out(endLabel)
|
jump.identifier!=null -> asmSymbolName(jump.identifier!!)
|
||||||
|
jump.address!=null -> jump.address!!.toHex()
|
||||||
|
else -> throw AssemblyError("weird jump")
|
||||||
|
}
|
||||||
|
when(stmt.condition.type) {
|
||||||
|
in WordDatatypes -> translateWordEqualsJump(stmt.condition, zero, leftConst, zero, label)
|
||||||
|
in ByteDatatypes -> translateByteEqualsJump(stmt.condition, zero, leftConst, zero, label)
|
||||||
|
else -> throw AssemblyError("weird condition dt")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val endLabel = makeLabel("if_end")
|
||||||
|
when(stmt.condition.type) {
|
||||||
|
in WordDatatypes -> translateWordEqualsJump(stmt.condition, zero, leftConst, zero, endLabel)
|
||||||
|
in ByteDatatypes -> translateByteEqualsJump(stmt.condition, zero, leftConst, zero, endLabel)
|
||||||
|
else -> throw AssemblyError("weird condition dt")
|
||||||
|
}
|
||||||
|
translate(stmt.ifScope)
|
||||||
|
out(endLabel)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// both true and else parts
|
||||||
|
val elseLabel = makeLabel("if_else")
|
||||||
|
val endLabel = makeLabel("if_end")
|
||||||
|
when(stmt.condition.type) {
|
||||||
|
in WordDatatypes -> translateWordEqualsJump(stmt.condition, zero, leftConst, zero, elseLabel)
|
||||||
|
in ByteDatatypes -> translateByteEqualsJump(stmt.condition, zero, leftConst, zero, elseLabel)
|
||||||
|
else -> throw AssemblyError("weird condition dt")
|
||||||
|
}
|
||||||
|
translate(stmt.ifScope)
|
||||||
|
jmp(endLabel)
|
||||||
|
out(elseLabel)
|
||||||
|
translate(stmt.elseScope)
|
||||||
|
out(endLabel)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -740,7 +779,7 @@ $repeatLabel lda $counterVar
|
|||||||
}
|
}
|
||||||
val isNested = parent is PtRepeatLoop
|
val isNested = parent is PtRepeatLoop
|
||||||
|
|
||||||
if(!isNested && !options.useNewExprCode) {
|
if(!isNested) {
|
||||||
// we can re-use a counter var from the subroutine if it already has one for that datatype
|
// we can re-use a counter var from the subroutine if it already has one for that datatype
|
||||||
val existingVar = asmInfo.extraVars.firstOrNull { it.first==dt && it.second.endsWith("counter") }
|
val existingVar = asmInfo.extraVars.firstOrNull { it.first==dt && it.second.endsWith("counter") }
|
||||||
if(existingVar!=null) {
|
if(existingVar!=null) {
|
||||||
@ -987,6 +1026,7 @@ $repeatLabel lda $counterVar
|
|||||||
val operator: String
|
val operator: String
|
||||||
|
|
||||||
if (pointerOffsetExpr is PtBinaryExpression) {
|
if (pointerOffsetExpr is PtBinaryExpression) {
|
||||||
|
require(!options.useNewExprCode)
|
||||||
operator = pointerOffsetExpr.operator
|
operator = pointerOffsetExpr.operator
|
||||||
left = pointerOffsetExpr.left
|
left = pointerOffsetExpr.left
|
||||||
right = pointerOffsetExpr.right
|
right = pointerOffsetExpr.right
|
||||||
@ -2853,6 +2893,7 @@ $repeatLabel lda $counterVar
|
|||||||
out(" sta P8ESTACK_LO,x | dex")
|
out(" sta P8ESTACK_LO,x | dex")
|
||||||
}
|
}
|
||||||
is PtBinaryExpression -> {
|
is PtBinaryExpression -> {
|
||||||
|
require(!options.useNewExprCode)
|
||||||
val addrExpr = expr.address as PtBinaryExpression
|
val addrExpr = expr.address as PtBinaryExpression
|
||||||
if(tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
if(tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
||||||
if(pushResultOnEstack)
|
if(pushResultOnEstack)
|
||||||
|
@ -662,6 +662,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is PtBinaryExpression -> {
|
is PtBinaryExpression -> {
|
||||||
|
require(!asmgen.options.useNewExprCode)
|
||||||
val result = asmgen.pointerViaIndexRegisterPossible(addrExpr)
|
val result = asmgen.pointerViaIndexRegisterPossible(addrExpr)
|
||||||
val pointer = result?.first as? PtIdentifier
|
val pointer = result?.first as? PtIdentifier
|
||||||
if(result!=null && pointer!=null && asmgen.isZpVar(pointer)) {
|
if(result!=null && pointer!=null && asmgen.isZpVar(pointer)) {
|
||||||
@ -724,6 +725,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
} else fallback()
|
} else fallback()
|
||||||
}
|
}
|
||||||
is PtBinaryExpression -> {
|
is PtBinaryExpression -> {
|
||||||
|
require(!asmgen.options.useNewExprCode)
|
||||||
val result = asmgen.pointerViaIndexRegisterPossible(addrExpr)
|
val result = asmgen.pointerViaIndexRegisterPossible(addrExpr)
|
||||||
val pointer = result?.first as? PtIdentifier
|
val pointer = result?.first as? PtIdentifier
|
||||||
if(result!=null && pointer!=null && asmgen.isZpVar(pointer)) {
|
if(result!=null && pointer!=null && asmgen.isZpVar(pointer)) {
|
||||||
|
@ -245,6 +245,8 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translateExpression(expr: PtBinaryExpression) {
|
private fun translateExpression(expr: PtBinaryExpression) {
|
||||||
|
require(!asmgen.options.useNewExprCode)
|
||||||
|
|
||||||
// Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED!
|
// Uses evalstack to evaluate the given expression. THIS IS SLOW AND SHOULD BE AVOIDED!
|
||||||
if(translateSomewhatOptimized(expr.left, expr.operator, expr.right))
|
if(translateSomewhatOptimized(expr.left, expr.operator, expr.right))
|
||||||
return
|
return
|
||||||
|
@ -147,6 +147,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
assignMemoryByte(assign.target, null, value.address as PtIdentifier)
|
assignMemoryByte(assign.target, null, value.address as PtIdentifier)
|
||||||
}
|
}
|
||||||
is PtBinaryExpression -> {
|
is PtBinaryExpression -> {
|
||||||
|
require(!asmgen.options.useNewExprCode)
|
||||||
val addrExpr = value.address as PtBinaryExpression
|
val addrExpr = value.address as PtBinaryExpression
|
||||||
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
||||||
assignRegisterByte(assign.target, CpuRegister.A)
|
assignRegisterByte(assign.target, CpuRegister.A)
|
||||||
@ -301,6 +302,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
assignRegisterByte(assign.target, CpuRegister.A)
|
assignRegisterByte(assign.target, CpuRegister.A)
|
||||||
}
|
}
|
||||||
is PtBinaryExpression -> {
|
is PtBinaryExpression -> {
|
||||||
|
require(!asmgen.options.useNewExprCode)
|
||||||
if(!attemptAssignOptimizedBinexpr(value, assign)) {
|
if(!attemptAssignOptimizedBinexpr(value, assign)) {
|
||||||
// All remaining binary expressions just evaluate via the stack for now.
|
// All remaining binary expressions just evaluate via the stack for now.
|
||||||
// (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here,
|
// (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here,
|
||||||
@ -346,6 +348,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
private fun attemptAssignOptimizedBinexpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||||
|
require(!asmgen.options.useNewExprCode)
|
||||||
if(expr.operator in ComparisonOperators) {
|
if(expr.operator in ComparisonOperators) {
|
||||||
if(expr.right.asConstInteger() == 0) {
|
if(expr.right.asConstInteger() == 0) {
|
||||||
if(expr.operator == "==" || expr.operator=="!=") {
|
if(expr.operator == "==" || expr.operator=="!=") {
|
||||||
@ -728,6 +731,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun attemptAssignToByteCompareZero(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
private fun attemptAssignToByteCompareZero(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||||
|
require(!asmgen.options.useNewExprCode)
|
||||||
when (expr.operator) {
|
when (expr.operator) {
|
||||||
"==" -> {
|
"==" -> {
|
||||||
when(val dt = expr.left.type) {
|
when(val dt = expr.left.type) {
|
||||||
@ -907,6 +911,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
assignMemoryByteIntoWord(target, null, value.address as PtIdentifier)
|
assignMemoryByteIntoWord(target, null, value.address as PtIdentifier)
|
||||||
}
|
}
|
||||||
is PtBinaryExpression -> {
|
is PtBinaryExpression -> {
|
||||||
|
require(!asmgen.options.useNewExprCode)
|
||||||
val addrExpr = value.address as PtBinaryExpression
|
val addrExpr = value.address as PtBinaryExpression
|
||||||
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
||||||
asmgen.out(" ldy #0")
|
asmgen.out(" ldy #0")
|
||||||
@ -2519,7 +2524,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assignConstantFloat(target: AsmAssignTarget, float: Double) {
|
internal fun assignConstantFloat(target: AsmAssignTarget, float: Double) {
|
||||||
if (float == 0.0) {
|
if (float == 0.0) {
|
||||||
// optimized case for float zero
|
// optimized case for float zero
|
||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
@ -2829,6 +2834,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
asmgen.storeAIntoPointerVar(addressExpr)
|
asmgen.storeAIntoPointerVar(addressExpr)
|
||||||
}
|
}
|
||||||
addressExpr is PtBinaryExpression -> {
|
addressExpr is PtBinaryExpression -> {
|
||||||
|
require(!asmgen.options.useNewExprCode)
|
||||||
if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.operator, true))
|
if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.operator, true))
|
||||||
storeViaExprEval()
|
storeViaExprEval()
|
||||||
}
|
}
|
||||||
|
@ -1319,8 +1319,174 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
|||||||
lda #0
|
lda #0
|
||||||
sta $name+1""")
|
sta $name+1""")
|
||||||
}
|
}
|
||||||
// pretty uncommon, who's going to assign a comparison boolean expresion to a word var?:
|
"<" -> {
|
||||||
"<", "<=", ">", ">=" -> TODO("word-litval-to-var comparisons")
|
if(dt==DataType.UWORD) {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $name+1
|
||||||
|
cmp #>$value
|
||||||
|
bcc ++
|
||||||
|
bne +
|
||||||
|
lda $name
|
||||||
|
cmp #<$value
|
||||||
|
bcc ++
|
||||||
|
+ lda #0 ; false
|
||||||
|
sta $name
|
||||||
|
sta $name+1
|
||||||
|
beq ++
|
||||||
|
+ lda #1 ; true
|
||||||
|
sta $name
|
||||||
|
lda #0
|
||||||
|
sta $name+1
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// signed
|
||||||
|
asmgen.out("""
|
||||||
|
lda $name
|
||||||
|
cmp #<$value
|
||||||
|
lda $name+1
|
||||||
|
sbc #>$value
|
||||||
|
bvc +
|
||||||
|
eor #$80
|
||||||
|
+ bmi +
|
||||||
|
lda #0
|
||||||
|
sta $name
|
||||||
|
sta $name+1
|
||||||
|
beq ++
|
||||||
|
+ lda #1 ; true
|
||||||
|
sta $name
|
||||||
|
lda #0
|
||||||
|
sta $name+1
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"<=" -> {
|
||||||
|
if(dt==DataType.UWORD) {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $name+1
|
||||||
|
cmp #>$value
|
||||||
|
beq +
|
||||||
|
bcc ++
|
||||||
|
- lda #0 ; false
|
||||||
|
sta $name
|
||||||
|
sta $name+1
|
||||||
|
beq +++
|
||||||
|
+ lda $name ; next
|
||||||
|
cmp #<$value
|
||||||
|
bcc +
|
||||||
|
bne -
|
||||||
|
+ lda #1 ; true
|
||||||
|
sta $name
|
||||||
|
lda #0
|
||||||
|
sta $name+1
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// signed
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<$value
|
||||||
|
cmp $name
|
||||||
|
lda #>$value
|
||||||
|
sbc $name+1
|
||||||
|
bvc +
|
||||||
|
eor #$80
|
||||||
|
+ bpl +
|
||||||
|
lda #0
|
||||||
|
sta $name
|
||||||
|
sta $name+1
|
||||||
|
beq ++
|
||||||
|
+ lda #1
|
||||||
|
sta $name
|
||||||
|
lda #0
|
||||||
|
sta $name+1
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
">" -> {
|
||||||
|
// word > value --> value < word
|
||||||
|
if(dt==DataType.UWORD) {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #>$value
|
||||||
|
cmp $name+1
|
||||||
|
bcc ++
|
||||||
|
bne +
|
||||||
|
lda #<$value
|
||||||
|
cmp $name
|
||||||
|
bcc ++
|
||||||
|
+ lda #0 ; false
|
||||||
|
sta $name
|
||||||
|
sta $name+1
|
||||||
|
beq ++
|
||||||
|
+ lda #1 ; true
|
||||||
|
sta $name
|
||||||
|
lda #0
|
||||||
|
sta $name+1
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// signed
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<$value
|
||||||
|
cmp $name
|
||||||
|
lda #>$value
|
||||||
|
sbc $name+1
|
||||||
|
bvc +
|
||||||
|
eor #$80
|
||||||
|
+ bmi +
|
||||||
|
lda #0
|
||||||
|
sta $name
|
||||||
|
sta $name+1
|
||||||
|
beq ++
|
||||||
|
+ lda #1 ; true
|
||||||
|
sta $name
|
||||||
|
lda #0
|
||||||
|
sta $name+1
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
">=" -> {
|
||||||
|
// word >= value --> value <= word
|
||||||
|
if(dt==DataType.UWORD) {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #>$value
|
||||||
|
cmp $name+1
|
||||||
|
beq +
|
||||||
|
bcc ++
|
||||||
|
- lda #0 ; false
|
||||||
|
sta $name
|
||||||
|
sta $name+1
|
||||||
|
beq +++
|
||||||
|
+ lda #<$value ; next
|
||||||
|
cmp $name
|
||||||
|
bcc +
|
||||||
|
bne -
|
||||||
|
+ lda #1 ; true
|
||||||
|
sta $name
|
||||||
|
lda #0
|
||||||
|
sta $name+1
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// signed
|
||||||
|
asmgen.out("""
|
||||||
|
lda $name
|
||||||
|
cmp #<$value
|
||||||
|
lda $name+1
|
||||||
|
sbc #>$value
|
||||||
|
bvc +
|
||||||
|
eor #$80
|
||||||
|
+ bpl +
|
||||||
|
lda #0
|
||||||
|
sta $name
|
||||||
|
sta $name+1
|
||||||
|
beq ++
|
||||||
|
+ lda #1
|
||||||
|
sta $name
|
||||||
|
lda #0
|
||||||
|
sta $name+1
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2129,8 +2295,126 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
|||||||
jsr floats.FDIV
|
jsr floats.FDIV
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
// pretty uncommon, who's going to assign a comparison boolean expresion to a float var:
|
"==" -> {
|
||||||
"==", "!=", "<", "<=", ">", ">=" -> TODO("float-litval-to-var comparisons")
|
asmgen.out("""
|
||||||
|
lda #<$name
|
||||||
|
ldy #>$name
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
lda #<$constValueName
|
||||||
|
ldy #>$constValueName
|
||||||
|
jsr floats.vars_equal_f
|
||||||
|
bne +""")
|
||||||
|
val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name)
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 0.0)
|
||||||
|
asmgen.out("""
|
||||||
|
jmp ++
|
||||||
|
+""")
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 1.0)
|
||||||
|
asmgen.out("+")
|
||||||
|
asmgen.restoreRegisterLocal(CpuRegister.X)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
"!=" -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<$name
|
||||||
|
ldy #>$name
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
lda #<$constValueName
|
||||||
|
ldy #>$constValueName
|
||||||
|
jsr floats.vars_equal_f
|
||||||
|
beq +""")
|
||||||
|
val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name)
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 0.0)
|
||||||
|
asmgen.out("""
|
||||||
|
jmp ++
|
||||||
|
+""")
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 1.0)
|
||||||
|
asmgen.out("+")
|
||||||
|
asmgen.restoreRegisterLocal(CpuRegister.X)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
"<" -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<$name
|
||||||
|
ldy #>$name
|
||||||
|
jsr floats.MOVFM
|
||||||
|
lda #<$constValueName
|
||||||
|
ldy #>$constValueName
|
||||||
|
jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than
|
||||||
|
cmp #0
|
||||||
|
bmi +""")
|
||||||
|
val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name)
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 0.0)
|
||||||
|
asmgen.out("""
|
||||||
|
jmp ++
|
||||||
|
+""")
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 1.0)
|
||||||
|
asmgen.out("+")
|
||||||
|
asmgen.restoreRegisterLocal(CpuRegister.X)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
"<=" -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<$constValueName
|
||||||
|
ldy #>$constValueName
|
||||||
|
jsr floats.MOVFM
|
||||||
|
lda #<$name
|
||||||
|
ldy #>$name
|
||||||
|
jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than
|
||||||
|
cmp #0
|
||||||
|
bpl +""")
|
||||||
|
val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name)
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 0.0)
|
||||||
|
asmgen.out("""
|
||||||
|
jmp ++
|
||||||
|
+""")
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 1.0)
|
||||||
|
asmgen.out("+")
|
||||||
|
asmgen.restoreRegisterLocal(CpuRegister.X)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
">" -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<$constValueName
|
||||||
|
ldy #>$constValueName
|
||||||
|
jsr floats.MOVFM
|
||||||
|
lda #<$name
|
||||||
|
ldy #>$name
|
||||||
|
jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than
|
||||||
|
cmp #0
|
||||||
|
bmi +""")
|
||||||
|
val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name)
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 0.0)
|
||||||
|
asmgen.out("""
|
||||||
|
jmp ++
|
||||||
|
+""")
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 1.0)
|
||||||
|
asmgen.out("+")
|
||||||
|
asmgen.restoreRegisterLocal(CpuRegister.X)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
">=" -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<$name
|
||||||
|
ldy #>$name
|
||||||
|
jsr floats.MOVFM
|
||||||
|
lda #<$constValueName
|
||||||
|
ldy #>$constValueName
|
||||||
|
jsr floats.FCOMP ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than
|
||||||
|
cmp #0
|
||||||
|
bpl +""")
|
||||||
|
val nameTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.FLOAT, scope, Position.DUMMY, variableAsmName = name)
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 0.0)
|
||||||
|
asmgen.out("""
|
||||||
|
jmp ++
|
||||||
|
+""")
|
||||||
|
assignmentAsmGen.assignConstantFloat(nameTarget, 1.0)
|
||||||
|
asmgen.out("+")
|
||||||
|
asmgen.restoreRegisterLocal(CpuRegister.X)
|
||||||
|
return
|
||||||
|
}
|
||||||
else -> throw AssemblyError("invalid operator for in-place float modification $operator")
|
else -> throw AssemblyError("invalid operator for in-place float modification $operator")
|
||||||
}
|
}
|
||||||
// store Fac1 back into memory
|
// store Fac1 back into memory
|
||||||
|
@ -14,11 +14,6 @@ class ExperiCodeGen: ICodeGeneratorBackend {
|
|||||||
errors: IErrorReporter
|
errors: IErrorReporter
|
||||||
): IAssemblyProgram? {
|
): IAssemblyProgram? {
|
||||||
|
|
||||||
if(options.useNewExprCode) {
|
|
||||||
// TODO("transform BinExprs?")
|
|
||||||
// errors.warn("EXPERIMENTAL NEW EXPRESSION CODEGEN IS USED. CODE SIZE+SPEED POSSIBLY SUFFERS.", Position.DUMMY)
|
|
||||||
}
|
|
||||||
|
|
||||||
// you could write a code generator directly on the PtProgram AST,
|
// you could write a code generator directly on the PtProgram AST,
|
||||||
// but you can also use the Intermediate Representation to build a codegen on:
|
// but you can also use the Intermediate Representation to build a codegen on:
|
||||||
val irCodeGen = IRCodeGen(program, symbolTable, options, errors)
|
val irCodeGen = IRCodeGen(program, symbolTable, options, errors)
|
||||||
|
@ -93,7 +93,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
} else {
|
} else {
|
||||||
require(origAssign.operator.endsWith('='))
|
require(origAssign.operator.endsWith('='))
|
||||||
if(codeGen.options.useNewExprCode) {
|
if(codeGen.options.useNewExprCode) {
|
||||||
TODO("use something else than a BinExpr?")
|
TODO("use something else than a BinExpr")
|
||||||
} else {
|
} else {
|
||||||
value = PtBinaryExpression(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position)
|
value = PtBinaryExpression(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position)
|
||||||
val left: PtExpression = origAssign.target.children.single() as PtExpression
|
val left: PtExpression = origAssign.target.children.single() as PtExpression
|
||||||
@ -268,7 +268,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
} else {
|
} else {
|
||||||
val mult : PtExpression
|
val mult : PtExpression
|
||||||
if(codeGen.options.useNewExprCode) {
|
if(codeGen.options.useNewExprCode) {
|
||||||
TODO("use something else than a BinExpr?")
|
TODO("use something else than a BinExpr")
|
||||||
} else {
|
} else {
|
||||||
mult = PtBinaryExpression("*", DataType.UBYTE, array.position)
|
mult = PtBinaryExpression("*", DataType.UBYTE, array.position)
|
||||||
mult.children += array.index
|
mult.children += array.index
|
||||||
|
@ -320,6 +320,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(binExpr: PtBinaryExpression): ExpressionCodeResult {
|
private fun translate(binExpr: PtBinaryExpression): ExpressionCodeResult {
|
||||||
|
require(!codeGen.options.useNewExprCode)
|
||||||
val vmDt = codeGen.irType(binExpr.left.type)
|
val vmDt = codeGen.irType(binExpr.left.type)
|
||||||
val signed = binExpr.left.type in SignedDatatypes
|
val signed = binExpr.left.type in SignedDatatypes
|
||||||
return when(binExpr.operator) {
|
return when(binExpr.operator) {
|
||||||
|
@ -899,6 +899,7 @@ class IRCodeGen(
|
|||||||
val goto = ifElse.ifScope.children.firstOrNull() as? PtJump
|
val goto = ifElse.ifScope.children.firstOrNull() as? PtJump
|
||||||
when (condition) {
|
when (condition) {
|
||||||
is PtBinaryExpression -> {
|
is PtBinaryExpression -> {
|
||||||
|
require(!options.useNewExprCode)
|
||||||
if(condition.operator !in ComparisonOperators)
|
if(condition.operator !in ComparisonOperators)
|
||||||
throw AssemblyError("if condition should only be a binary comparison expression")
|
throw AssemblyError("if condition should only be a binary comparison expression")
|
||||||
|
|
||||||
|
@ -14,13 +14,6 @@ class VmCodeGen: ICodeGeneratorBackend {
|
|||||||
options: CompilationOptions,
|
options: CompilationOptions,
|
||||||
errors: IErrorReporter
|
errors: IErrorReporter
|
||||||
): IAssemblyProgram? {
|
): IAssemblyProgram? {
|
||||||
|
|
||||||
if(options.useNewExprCode) {
|
|
||||||
// TODO("transform BinExprs?")
|
|
||||||
// errors.warn("EXPERIMENTAL NEW EXPRESSION CODEGEN IS USED. CODE SIZE+SPEED POSSIBLY SUFFERS.", Position.DUMMY)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val irCodeGen = IRCodeGen(program, symbolTable, options, errors)
|
val irCodeGen = IRCodeGen(program, symbolTable, options, errors)
|
||||||
val irProgram = irCodeGen.generate()
|
val irProgram = irCodeGen.generate()
|
||||||
return VmAssemblyProgram(irProgram.name, irProgram)
|
return VmAssemblyProgram(irProgram.name, irProgram)
|
||||||
|
@ -251,7 +251,7 @@ pop_float_fac1 .proc
|
|||||||
.pend
|
.pend
|
||||||
|
|
||||||
copy_float .proc
|
copy_float .proc
|
||||||
; -- copies the 5 bytes of the mflt value pointed to by SCRATCH_ZPWORD1,
|
; -- copies the 5 bytes of the mflt value pointed to by SCRATCH_W1,
|
||||||
; into the 5 bytes pointed to by A/Y. Clobbers A,Y.
|
; into the 5 bytes pointed to by A/Y. Clobbers A,Y.
|
||||||
sta _target+1
|
sta _target+1
|
||||||
sty _target+2
|
sty _target+2
|
||||||
|
@ -8,7 +8,7 @@ import prog8.ast.expressions.Expression
|
|||||||
import prog8.ast.expressions.NumericLiteral
|
import prog8.ast.expressions.NumericLiteral
|
||||||
import prog8.ast.statements.Directive
|
import prog8.ast.statements.Directive
|
||||||
import prog8.code.SymbolTableMaker
|
import prog8.code.SymbolTableMaker
|
||||||
import prog8.code.ast.PtProgram
|
import prog8.code.ast.*
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import prog8.code.target.*
|
import prog8.code.target.*
|
||||||
import prog8.codegen.vm.VmCodeGen
|
import prog8.codegen.vm.VmCodeGen
|
||||||
@ -409,6 +409,11 @@ private fun createAssemblyAndAssemble(program: PtProgram,
|
|||||||
else
|
else
|
||||||
throw NotImplementedError("no code generator for cpu ${compilerOptions.compTarget.machine.cpu}")
|
throw NotImplementedError("no code generator for cpu ${compilerOptions.compTarget.machine.cpu}")
|
||||||
|
|
||||||
|
if(compilerOptions.useNewExprCode)
|
||||||
|
transformNewExpressions(program)
|
||||||
|
|
||||||
|
printAst(program, true) { println(it) }
|
||||||
|
|
||||||
val stMaker = SymbolTableMaker(program, compilerOptions)
|
val stMaker = SymbolTableMaker(program, compilerOptions)
|
||||||
val symbolTable = stMaker.make()
|
val symbolTable = stMaker.make()
|
||||||
val assembly = asmgen.generate(program, symbolTable, compilerOptions, errors)
|
val assembly = asmgen.generate(program, symbolTable, compilerOptions, errors)
|
||||||
@ -420,3 +425,165 @@ private fun createAssemblyAndAssemble(program: PtProgram,
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun transformNewExpressions(program: PtProgram) {
|
||||||
|
val newVariables = mutableMapOf<PtSub, MutableList<PtVariable>>()
|
||||||
|
|
||||||
|
fun getExprVar(what: String, type: DataType, count: Int, pos: Position, scope: PtSub): PtIdentifier {
|
||||||
|
val name = "p8p_exprvar_${what}_${count}_${type.toString().lowercase()}"
|
||||||
|
var subVars = newVariables[scope]
|
||||||
|
if(subVars==null) {
|
||||||
|
subVars = mutableListOf()
|
||||||
|
newVariables[scope] = subVars
|
||||||
|
}
|
||||||
|
if(subVars.all { it.name!=name }) {
|
||||||
|
subVars.add(PtVariable(name, type, ZeropageWish.DONTCARE, null, null, pos))
|
||||||
|
}
|
||||||
|
return PtIdentifier("${scope.scopedName}.$name", type, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun transformExpr(expr: PtBinaryExpression, postfix: String, depth: Int): Pair<PtExpression, List<IPtAssignment>> {
|
||||||
|
// depth first process the expression tree
|
||||||
|
val scope = expr.definingSub()!!
|
||||||
|
val assignments = mutableListOf<IPtAssignment>()
|
||||||
|
|
||||||
|
fun transformOperand(node: PtExpression, kind: String): PtNode {
|
||||||
|
return when(node) {
|
||||||
|
is PtNumber, is PtIdentifier, is PtArray, is PtString, is PtMachineRegister -> node
|
||||||
|
is PtBinaryExpression -> {
|
||||||
|
val (replacement, subAssigns) = transformExpr(node, kind, depth+1)
|
||||||
|
assignments.addAll(subAssigns)
|
||||||
|
replacement
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val variable = getExprVar(kind, node.type, depth, node.position, scope)
|
||||||
|
val assign = PtAssignment(node.position)
|
||||||
|
val target = PtAssignTarget(variable.position)
|
||||||
|
target.add(variable)
|
||||||
|
assign.add(target)
|
||||||
|
assign.add(node)
|
||||||
|
assignments.add(assign)
|
||||||
|
variable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val newLeft = transformOperand(expr.left,"l")
|
||||||
|
val newRight = transformOperand(expr.right, "r")
|
||||||
|
|
||||||
|
// process the binexpr
|
||||||
|
|
||||||
|
val resultVar =
|
||||||
|
if(expr.type == expr.left.type) {
|
||||||
|
getExprVar(postfix, expr.type, depth, expr.position, scope)
|
||||||
|
} else {
|
||||||
|
if(expr.operator in ComparisonOperators && expr.type == DataType.UBYTE) {
|
||||||
|
// this is very common and should be dealth with correctly; byte==0, word>42
|
||||||
|
getExprVar(postfix, expr.left.type, depth, expr.position, scope)
|
||||||
|
}
|
||||||
|
else if(expr.left.type in PassByReferenceDatatypes && expr.type==DataType.UBYTE) {
|
||||||
|
// this is common and should be dealth with correctly; for instance "name"=="irmen"
|
||||||
|
getExprVar(postfix, expr.left.type, depth, expr.position, scope)
|
||||||
|
} else {
|
||||||
|
TODO("expression type differs from left operand type! got ${expr.left.type} expected ${expr.type} ${expr.position}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(resultVar.name!=(newLeft as? PtIdentifier)?.name) {
|
||||||
|
// resultvar = left
|
||||||
|
val assign1 = PtAssignment(newLeft.position)
|
||||||
|
val target1 = PtAssignTarget(resultVar.position)
|
||||||
|
target1.add(resultVar)
|
||||||
|
assign1.add(target1)
|
||||||
|
assign1.add(newLeft)
|
||||||
|
assignments.add(assign1)
|
||||||
|
}
|
||||||
|
// resultvar {oper}= right
|
||||||
|
val operator = if(expr.operator in ComparisonOperators) expr.operator else expr.operator+'='
|
||||||
|
val assign2 = PtAugmentedAssign(operator, newRight.position)
|
||||||
|
val target2 = PtAssignTarget(resultVar.position)
|
||||||
|
target2.add(resultVar.copy())
|
||||||
|
assign2.add(target2)
|
||||||
|
assign2.add(newRight)
|
||||||
|
assignments.add(assign2)
|
||||||
|
return Pair(resultVar, assignments)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isProperStatement(node: PtNode): Boolean {
|
||||||
|
return when(node) {
|
||||||
|
is PtAssignment -> true
|
||||||
|
is PtAugmentedAssign -> true
|
||||||
|
is PtBreakpoint -> true
|
||||||
|
is PtConditionalBranch -> true
|
||||||
|
is PtForLoop -> true
|
||||||
|
is PtIfElse -> true
|
||||||
|
is PtIncludeBinary -> true
|
||||||
|
is PtInlineAssembly -> true
|
||||||
|
is PtJump -> true
|
||||||
|
is PtAsmSub -> true
|
||||||
|
is PtLabel -> true
|
||||||
|
is PtSub -> true
|
||||||
|
is PtVariable -> true
|
||||||
|
is PtNop -> true
|
||||||
|
is PtPostIncrDecr -> true
|
||||||
|
is PtRepeatLoop -> true
|
||||||
|
is PtReturn -> true
|
||||||
|
is PtWhen -> true
|
||||||
|
is PtBuiltinFunctionCall -> node.void
|
||||||
|
is PtFunctionCall -> node.void
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun transform(node: PtNode, parent: PtNode, depth: Int) {
|
||||||
|
if(node is PtBinaryExpression) {
|
||||||
|
node.children.toTypedArray().forEach {
|
||||||
|
transform(it, node, depth+1)
|
||||||
|
}
|
||||||
|
val (rep, assignments) = transformExpr(node, "l", depth)
|
||||||
|
var replacement = rep
|
||||||
|
if(!(rep.type equalsSize node.type)) {
|
||||||
|
if(rep.type in NumericDatatypes && node.type in ByteDatatypes) {
|
||||||
|
replacement = PtTypeCast(node.type, node.position)
|
||||||
|
replacement.add(rep)
|
||||||
|
} else
|
||||||
|
TODO("cast replacement type ${rep.type} -> ${node.type}")
|
||||||
|
}
|
||||||
|
var idx = parent.children.indexOf(node)
|
||||||
|
parent.children[idx] = replacement
|
||||||
|
replacement.parent = parent
|
||||||
|
// find the statement above which we should insert the assignments
|
||||||
|
var stmt = node
|
||||||
|
while(!isProperStatement(stmt))
|
||||||
|
stmt = stmt.parent
|
||||||
|
idx = stmt.parent.children.indexOf(stmt)
|
||||||
|
assignments.reversed().forEach {
|
||||||
|
stmt.parent.add(idx, it as PtNode)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
node.children.toTypedArray().forEach { child -> transform(child, node, depth+1) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
program.allBlocks().forEach { block ->
|
||||||
|
block.children.toTypedArray().forEach {
|
||||||
|
transform(it, block, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the new variables
|
||||||
|
newVariables.forEach { (sub, vars) ->
|
||||||
|
vars.forEach {
|
||||||
|
sub.add(0, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// extra check to see that all PtBinaryExpressions have been transformed
|
||||||
|
fun binExprCheck(node: PtNode) {
|
||||||
|
if(node is PtBinaryExpression)
|
||||||
|
throw IllegalArgumentException("still got binexpr $node ${node.position}")
|
||||||
|
node.children.forEach { binExprCheck(it) }
|
||||||
|
}
|
||||||
|
binExprCheck(program)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -957,7 +957,11 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(expr.operator !in ComparisonOperators) {
|
if(expr.operator in ComparisonOperators) {
|
||||||
|
if(leftDt!=rightDt && !(leftDt in ByteDatatypes && rightDt in ByteDatatypes)) {
|
||||||
|
throw FatalAstException("got comparison with different operand types: $leftDt ${expr.operator} $rightDt ${expr.position}")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (leftDt == DataType.STR && rightDt == DataType.STR || leftDt in ArrayDatatypes && rightDt in ArrayDatatypes) {
|
if (leftDt == DataType.STR && rightDt == DataType.STR || leftDt in ArrayDatatypes && rightDt in ArrayDatatypes) {
|
||||||
// str+str and str*number have already been const evaluated before we get here.
|
// str+str and str*number have already been const evaluated before we get here.
|
||||||
errors.err("no computational or logical expressions with strings or arrays are possible", expr.position)
|
errors.err("no computational or logical expressions with strings or arrays are possible", expr.position)
|
||||||
|
@ -109,6 +109,8 @@ internal class NotExpressionAndIfComparisonExprChanger(val program: Program, val
|
|||||||
if(binExpr==null || binExpr.operator !in ComparisonOperators)
|
if(binExpr==null || binExpr.operator !in ComparisonOperators)
|
||||||
return noModifications
|
return noModifications
|
||||||
|
|
||||||
|
return noModifications // TODO tijdelijk geen simplify
|
||||||
|
|
||||||
// Simplify the conditional expression, introduce simple assignments if required.
|
// Simplify the conditional expression, introduce simple assignments if required.
|
||||||
// This is REQUIRED for correct code generation on 6502 because evaluating certain expressions
|
// This is REQUIRED for correct code generation on 6502 because evaluating certain expressions
|
||||||
// clobber the handful of temporary variables in the zeropage and leaving everything in one
|
// clobber the handful of temporary variables in the zeropage and leaving everything in one
|
||||||
|
157
examples/test.p8
157
examples/test.p8
@ -1,38 +1,141 @@
|
|||||||
|
%zeropage basicsafe
|
||||||
%import textio
|
%import textio
|
||||||
%import floats
|
%import floats
|
||||||
%zeropage basicsafe
|
|
||||||
|
|
||||||
; Draw a mandelbrot in graphics mode (the image will be 256 x 200 pixels).
|
|
||||||
; NOTE: this will take an eternity to draw on a real c64. A CommanderX16 is a bit faster.
|
|
||||||
; even in Vice in warp mode (700% speed on my machine) it's slow, but you can see progress
|
|
||||||
|
|
||||||
; Note: this program is compatible with C64 and CX16.
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
float xsquared = 2.0
|
byte b = -100
|
||||||
float ysquared = 1.9
|
ubyte ub = 20
|
||||||
uword w = 1
|
word w = -20000
|
||||||
ubyte h = 0
|
uword uw = 2000
|
||||||
|
float f = -100
|
||||||
|
|
||||||
str name = ".tx2"
|
txt.print("all 1: ")
|
||||||
|
txt.print_ub(b == -100)
|
||||||
|
txt.print_ub(b != -99)
|
||||||
|
txt.print_ub(b < -99)
|
||||||
|
txt.print_ub(b <= -100)
|
||||||
|
txt.print_ub(b > -101)
|
||||||
|
txt.print_ub(b >= -100)
|
||||||
|
txt.print_ub(ub ==20)
|
||||||
|
txt.print_ub(ub !=19)
|
||||||
|
txt.print_ub(ub <21)
|
||||||
|
txt.print_ub(ub <=20)
|
||||||
|
txt.print_ub(ub>19)
|
||||||
|
txt.print_ub(ub>=20)
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(w == -20000)
|
||||||
|
txt.print_ub(w != -19999)
|
||||||
|
txt.print_ub(w < -19999)
|
||||||
|
txt.print_ub(w <= -20000)
|
||||||
|
txt.print_ub(w > -20001)
|
||||||
|
txt.print_ub(w >= -20000)
|
||||||
|
txt.print_ub(uw == 2000)
|
||||||
|
txt.print_ub(uw != 2001)
|
||||||
|
txt.print_ub(uw < 2001)
|
||||||
|
txt.print_ub(uw <= 2000)
|
||||||
|
txt.print_ub(uw > 1999)
|
||||||
|
txt.print_ub(uw >= 2000)
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(f == -100.0)
|
||||||
|
txt.print_ub(f != -99.0)
|
||||||
|
txt.print_ub(f < -99.0)
|
||||||
|
txt.print_ub(f <= -100.0)
|
||||||
|
txt.print_ub(f > -101.0)
|
||||||
|
txt.print_ub(f >= -100.0)
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
if name==".jpg" or name==".txt" or name==".gif" {
|
txt.print("all 0: ")
|
||||||
txt.print("yes")
|
txt.print_ub(b == -99)
|
||||||
|
txt.print_ub(b != -100)
|
||||||
|
txt.print_ub(b < -100)
|
||||||
|
txt.print_ub(b <= -101)
|
||||||
|
txt.print_ub(b > -100)
|
||||||
|
txt.print_ub(b >= -99)
|
||||||
|
txt.print_ub(ub ==21)
|
||||||
|
txt.print_ub(ub !=20)
|
||||||
|
txt.print_ub(ub <20)
|
||||||
|
txt.print_ub(ub <=19)
|
||||||
|
txt.print_ub(ub>20)
|
||||||
|
txt.print_ub(ub>=21)
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(w == -20001)
|
||||||
|
txt.print_ub(w != -20000)
|
||||||
|
txt.print_ub(w < -20000)
|
||||||
|
txt.print_ub(w <= -20001)
|
||||||
|
txt.print_ub(w > -20000)
|
||||||
|
txt.print_ub(w >= -19999)
|
||||||
|
txt.print_ub(uw == 1999)
|
||||||
|
txt.print_ub(uw != 2000)
|
||||||
|
txt.print_ub(uw < 2000)
|
||||||
|
txt.print_ub(uw <= 1999)
|
||||||
|
txt.print_ub(uw > 2000)
|
||||||
|
txt.print_ub(uw >= 2001)
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(f == -99.0)
|
||||||
|
txt.print_ub(f != -100.0)
|
||||||
|
txt.print_ub(f < -100.0)
|
||||||
|
txt.print_ub(f <= -101.0)
|
||||||
|
txt.print_ub(f > -100.0)
|
||||||
|
txt.print_ub(f >= -99.0)
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
|
; TODO ALL OF THE ABOVE BUT WITH A VARIABLE INSTEAD OF A CONST VALUE
|
||||||
|
|
||||||
|
|
||||||
|
b = -100
|
||||||
|
while b <= -20
|
||||||
|
b++
|
||||||
|
txt.print_b(b)
|
||||||
|
txt.print(" -19\n")
|
||||||
|
b = -100
|
||||||
|
while b < -20
|
||||||
|
b++
|
||||||
|
txt.print_b(b)
|
||||||
|
txt.print(" -20\n")
|
||||||
|
|
||||||
|
ub = 20
|
||||||
|
while ub <= 200
|
||||||
|
ub++
|
||||||
|
txt.print_ub(ub)
|
||||||
|
txt.print(" 201\n")
|
||||||
|
ub = 20
|
||||||
|
while ub < 200
|
||||||
|
ub++
|
||||||
|
txt.print_ub(ub)
|
||||||
|
txt.print(" 200\n")
|
||||||
|
|
||||||
|
w = -20000
|
||||||
|
while w <= -8000 {
|
||||||
|
w++
|
||||||
}
|
}
|
||||||
|
txt.print_w(w)
|
||||||
|
txt.print(" -7999\n")
|
||||||
|
w = -20000
|
||||||
|
while w < -8000 {
|
||||||
|
w++
|
||||||
|
}
|
||||||
|
txt.print_w(w)
|
||||||
|
txt.print(" -8000\n")
|
||||||
|
|
||||||
; if w==0 or xsquared+ysquared<4.0 {
|
uw = 2000
|
||||||
; txt.print("yes")
|
while uw <= 8000 {
|
||||||
; }
|
uw++
|
||||||
|
}
|
||||||
|
txt.print_uw(uw)
|
||||||
|
txt.print(" 8001\n")
|
||||||
|
uw = 2000
|
||||||
|
while uw < 8000 {
|
||||||
|
uw++
|
||||||
|
}
|
||||||
|
txt.print_uw(uw)
|
||||||
|
txt.print(" 8000\n")
|
||||||
|
|
||||||
; if w==0 {
|
f = 0.0
|
||||||
; txt.print("w=0 ")
|
while f<2.2 {
|
||||||
; }
|
f+=0.1
|
||||||
; if h==0 {
|
}
|
||||||
; txt.print("h=0 ")
|
floats.print_f(f)
|
||||||
; }
|
txt.print(" 2.2\n")
|
||||||
; if w==0 or h==0 {
|
|
||||||
; txt.print(" w or h=0")
|
|
||||||
; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user