mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
boolean vs byte cast fixing, and pointervar error
This commit is contained in:
parent
a5ca08f33d
commit
201b77d5b6
@ -113,10 +113,10 @@ class AsmGen(
|
|||||||
out(" lda $sourceName")
|
out(" lda $sourceName")
|
||||||
return sourceName
|
return sourceName
|
||||||
}
|
}
|
||||||
is PtVariable -> {
|
is PtVariable, is PtMemMapped -> {
|
||||||
val sourceName = asmVariableName(pointervar)
|
val sourceName = asmVariableName(pointervar)
|
||||||
if (isTargetCpu(CpuType.CPU65c02)) {
|
if (isTargetCpu(CpuType.CPU65c02)) {
|
||||||
return if (allocator.isZpVar(target.scopedName.split('.'))) { // TODO dotted string
|
return if (allocator.isZpVar((target as PtNamedNode).scopedName.split('.'))) { // TODO dotted string
|
||||||
// pointervar is already in the zero page, no need to copy
|
// pointervar is already in the zero page, no need to copy
|
||||||
out(" lda ($sourceName)")
|
out(" lda ($sourceName)")
|
||||||
sourceName
|
sourceName
|
||||||
@ -130,7 +130,7 @@ class AsmGen(
|
|||||||
"P8ZP_SCRATCH_W1"
|
"P8ZP_SCRATCH_W1"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return if (allocator.isZpVar(target.scopedName.split('.'))) { // TODO dotted string
|
return if (allocator.isZpVar((target as PtNamedNode).scopedName.split('.'))) { // TODO dotted string
|
||||||
// pointervar is already in the zero page, no need to copy
|
// pointervar is already in the zero page, no need to copy
|
||||||
out(" ldy #0 | lda ($sourceName),y")
|
out(" ldy #0 | lda ($sourceName),y")
|
||||||
sourceName
|
sourceName
|
||||||
@ -146,7 +146,7 @@ class AsmGen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("invalid pointervar")
|
else -> throw AssemblyError("invalid pointervar $target")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -995,7 +995,7 @@ $repeatLabel lda $counterVar
|
|||||||
out(" lda ${asmSymbolName(pointervar)},y")
|
out(" lda ${asmSymbolName(pointervar)},y")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
is PtVariable, null -> {
|
is IPtVariable, null -> {
|
||||||
if(write) {
|
if(write) {
|
||||||
if(pointervar!=null && isZpVar(pointervar)) {
|
if(pointervar!=null && isZpVar(pointervar)) {
|
||||||
val saveA = evalBytevalueWillClobberA(ptrAndIndex.second)
|
val saveA = evalBytevalueWillClobberA(ptrAndIndex.second)
|
||||||
@ -1045,7 +1045,7 @@ $repeatLabel lda $counterVar
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("invalid pointervar")
|
else -> throw AssemblyError("invalid pointervar $pointervar")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,3 +162,27 @@ internal fun IPtSubroutine.returnsWhatWhere(): List<Pair<DataType, RegisterOrSta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun PtExpression.clone(): PtExpression {
|
||||||
|
fun withClonedChildrenFrom(orig: PtExpression, clone: PtExpression): PtExpression {
|
||||||
|
orig.children.forEach { clone.add((it as PtExpression).clone()) }
|
||||||
|
return clone
|
||||||
|
}
|
||||||
|
when(this) {
|
||||||
|
is PtAddressOf -> return withClonedChildrenFrom(this, PtAddressOf(position))
|
||||||
|
is PtArray -> return withClonedChildrenFrom(this, PtArray(type, position))
|
||||||
|
is PtArrayIndexer -> return withClonedChildrenFrom(this, PtArrayIndexer(type, position))
|
||||||
|
is PtBinaryExpression -> return withClonedChildrenFrom(this, PtBinaryExpression(operator, type, position))
|
||||||
|
is PtBuiltinFunctionCall -> return withClonedChildrenFrom(this, PtBuiltinFunctionCall(name, void, hasNoSideEffects, type, position))
|
||||||
|
is PtContainmentCheck -> return withClonedChildrenFrom(this, PtContainmentCheck(position))
|
||||||
|
is PtFunctionCall -> return withClonedChildrenFrom(this, PtFunctionCall(name, void, type, position))
|
||||||
|
is PtIdentifier -> return withClonedChildrenFrom(this, PtIdentifier(name, type, position))
|
||||||
|
is PtMachineRegister -> return withClonedChildrenFrom(this, PtMachineRegister(register, type, position))
|
||||||
|
is PtMemoryByte -> return withClonedChildrenFrom(this, PtMemoryByte(position))
|
||||||
|
is PtNumber -> return withClonedChildrenFrom(this, PtNumber(type, number, position))
|
||||||
|
is PtPrefix -> return withClonedChildrenFrom(this, PtPrefix(operator, type, position))
|
||||||
|
is PtRange -> return withClonedChildrenFrom(this, PtRange(type, position))
|
||||||
|
is PtString -> return withClonedChildrenFrom(this, PtString(value, encoding, position))
|
||||||
|
is PtTypeCast -> return withClonedChildrenFrom(this, PtTypeCast(type, position))
|
||||||
|
}
|
||||||
|
}
|
@ -363,11 +363,12 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
assignTrue.add(assignment)
|
assignTrue.add(assignment)
|
||||||
val assignFalse = PtNodeGroup()
|
val assignFalse = PtNodeGroup()
|
||||||
val ifelse = PtIfElse(assign.position)
|
val ifelse = PtIfElse(assign.position)
|
||||||
val exprClone = arrayOf(expr).clone()[0]
|
val exprClone = PtBinaryExpression(expr.operator, expr.type, expr.position)
|
||||||
require(exprClone !== expr) // TODO remove check if it works
|
expr.children.forEach { exprClone.children.add(it) } // doesn't seem to need a deep clone
|
||||||
ifelse.add(expr)
|
ifelse.add(exprClone)
|
||||||
ifelse.add(assignTrue)
|
ifelse.add(assignTrue)
|
||||||
ifelse.add(assignFalse)
|
ifelse.add(assignFalse)
|
||||||
|
ifelse.parent = expr.parent
|
||||||
asmgen.translate(ifelse)
|
asmgen.translate(ifelse)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -136,12 +136,8 @@ internal fun Program.checkIdentifiers(errors: IErrorReporter, options: Compilati
|
|||||||
internal fun Program.variousCleanups(errors: IErrorReporter, options: CompilationOptions) {
|
internal fun Program.variousCleanups(errors: IErrorReporter, options: CompilationOptions) {
|
||||||
val process = VariousCleanups(this, errors, options)
|
val process = VariousCleanups(this, errors, options)
|
||||||
process.visit(this)
|
process.visit(this)
|
||||||
if(errors.noErrors()) {
|
while(errors.noErrors() && process.applyModifications()>0) { // TODO limit the number of cycles here?
|
||||||
if(process.applyModifications()>0) {
|
process.visit(this)
|
||||||
process.visit(this)
|
|
||||||
if(errors.noErrors())
|
|
||||||
process.applyModifications()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,11 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
||||||
|
if(assignment.target isSameAs assignment.value) {
|
||||||
|
// remove assignment to self
|
||||||
|
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
||||||
|
}
|
||||||
|
|
||||||
// remove duplicated assignments, but not if it's a memory mapped IO register
|
// remove duplicated assignments, but not if it's a memory mapped IO register
|
||||||
val isIO = try {
|
val isIO = try {
|
||||||
assignment.target.isIOAddress(options.compTarget.machine)
|
assignment.target.isIOAddress(options.compTarget.machine)
|
||||||
|
@ -120,6 +120,42 @@ main {
|
|||||||
right3.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
right3.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("simple logical with bool no typecast") {
|
||||||
|
val text="""
|
||||||
|
main {
|
||||||
|
bool bb
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
bb = bb and 123
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
val result = compileText(C64Target(), true, text, writeAssembly = true)!!
|
||||||
|
val stmts = result.program.entrypoint.statements
|
||||||
|
stmts.size shouldBe 2
|
||||||
|
val assignValue = (stmts[0] as Assignment).value as BinaryExpression
|
||||||
|
assignValue.left shouldBe instanceOf<IdentifierReference>()
|
||||||
|
assignValue.operator shouldBe "&"
|
||||||
|
(assignValue.right as NumericLiteral).number shouldBe 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
test("simple logical with byte instead of bool ok with typecasting") {
|
||||||
|
val text="""
|
||||||
|
main {
|
||||||
|
ubyte ubb
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
ubb = ubb and 123
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
val result = compileText(C64Target(), true, text, writeAssembly = true)!!
|
||||||
|
val stmts = result.program.entrypoint.statements
|
||||||
|
stmts.size shouldBe 2
|
||||||
|
val assignValue = (stmts[0] as Assignment).value as BinaryExpression
|
||||||
|
assignValue.left shouldBe instanceOf<BinaryExpression>() // as a result of the cast to boolean
|
||||||
|
assignValue.operator shouldBe "&"
|
||||||
|
(assignValue.right as NumericLiteral).number shouldBe 1.0
|
||||||
|
}
|
||||||
|
|
||||||
test("logical with byte instead of bool") {
|
test("logical with byte instead of bool") {
|
||||||
val text="""
|
val text="""
|
||||||
%import textio
|
%import textio
|
||||||
|
Loading…
Reference in New Issue
Block a user