mirror of
https://github.com/irmen/prog8.git
synced 2024-11-18 19:12:44 +00:00
fix constvalue parent linkage for prefix and typecast
This commit is contained in:
parent
cedfb17b18
commit
87600b23db
@ -5,6 +5,7 @@ import io.kotest.assertions.withClue
|
|||||||
import io.kotest.core.spec.style.FunSpec
|
import io.kotest.core.spec.style.FunSpec
|
||||||
import io.kotest.matchers.shouldBe
|
import io.kotest.matchers.shouldBe
|
||||||
import io.kotest.matchers.shouldNotBe
|
import io.kotest.matchers.shouldNotBe
|
||||||
|
import io.kotest.matchers.string.shouldContain
|
||||||
import io.kotest.matchers.types.instanceOf
|
import io.kotest.matchers.types.instanceOf
|
||||||
import io.kotest.matchers.types.shouldBeSameInstanceAs
|
import io.kotest.matchers.types.shouldBeSameInstanceAs
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
@ -16,6 +17,7 @@ import prog8.ast.statements.*
|
|||||||
import prog8.compiler.BeforeAsmGenerationAstChanger
|
import prog8.compiler.BeforeAsmGenerationAstChanger
|
||||||
import prog8.compiler.target.C64Target
|
import prog8.compiler.target.C64Target
|
||||||
import prog8.compilerinterface.*
|
import prog8.compilerinterface.*
|
||||||
|
import prog8tests.helpers.*
|
||||||
import prog8tests.helpers.DummyFunctions
|
import prog8tests.helpers.DummyFunctions
|
||||||
import prog8tests.helpers.DummyMemsizer
|
import prog8tests.helpers.DummyMemsizer
|
||||||
import prog8tests.helpers.DummyStringEncoder
|
import prog8tests.helpers.DummyStringEncoder
|
||||||
@ -73,7 +75,7 @@ class TestOptimization: FunSpec({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test("generated constvalue inherits proper parent linkage") {
|
test("generated constvalue from typecast inherits proper parent linkage") {
|
||||||
val number = NumericLiteralValue(DataType.UBYTE, 11.0, Position.DUMMY)
|
val number = NumericLiteralValue(DataType.UBYTE, 11.0, Position.DUMMY)
|
||||||
val tc = TypecastExpression(number, DataType.BYTE, false, Position.DUMMY)
|
val tc = TypecastExpression(number, DataType.BYTE, false, Position.DUMMY)
|
||||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||||
@ -83,9 +85,24 @@ class TestOptimization: FunSpec({
|
|||||||
tc shouldBeSameInstanceAs number.parent
|
tc shouldBeSameInstanceAs number.parent
|
||||||
val constvalue = tc.constValue(program)!!
|
val constvalue = tc.constValue(program)!!
|
||||||
constvalue shouldBe instanceOf<NumericLiteralValue>()
|
constvalue shouldBe instanceOf<NumericLiteralValue>()
|
||||||
constvalue.number.toInt() shouldBe 11
|
constvalue.number shouldBe 11.0
|
||||||
constvalue.type shouldBe DataType.BYTE
|
constvalue.type shouldBe DataType.BYTE
|
||||||
tc shouldBeSameInstanceAs constvalue.parent
|
constvalue.parent shouldBeSameInstanceAs tc.parent
|
||||||
|
}
|
||||||
|
|
||||||
|
test("generated constvalue from prefixexpr inherits proper parent linkage") {
|
||||||
|
val number = NumericLiteralValue(DataType.UBYTE, 11.0, Position.DUMMY)
|
||||||
|
val pfx = PrefixExpression("-", number, Position.DUMMY)
|
||||||
|
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||||
|
pfx.linkParents(ParentSentinel)
|
||||||
|
pfx.parent shouldNotBe null
|
||||||
|
number.parent shouldNotBe null
|
||||||
|
pfx shouldBeSameInstanceAs number.parent
|
||||||
|
val constvalue = pfx.constValue(program)!!
|
||||||
|
constvalue shouldBe instanceOf<NumericLiteralValue>()
|
||||||
|
constvalue.number shouldBe -11.0
|
||||||
|
constvalue.type shouldBe DataType.BYTE
|
||||||
|
constvalue.parent shouldBeSameInstanceAs pfx.parent
|
||||||
}
|
}
|
||||||
|
|
||||||
test("constantfolded and silently typecasted for initializervalues") {
|
test("constantfolded and silently typecasted for initializervalues") {
|
||||||
@ -410,8 +427,8 @@ class TestOptimization: FunSpec({
|
|||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte @shared z1 = 1
|
ubyte @shared z1 = 1
|
||||||
ubyte @shared z2 = +1
|
ubyte @shared z2 = + 1
|
||||||
ubyte @shared z3 = ~1
|
ubyte @shared z3 = ~ 1
|
||||||
ubyte @shared z4 = not 1
|
ubyte @shared z4 = not 1
|
||||||
byte @shared z5 = - 1
|
byte @shared z5 = - 1
|
||||||
}
|
}
|
||||||
@ -423,4 +440,19 @@ class TestOptimization: FunSpec({
|
|||||||
stmts.filterIsInstance<VarDecl>().size shouldBe 5
|
stmts.filterIsInstance<VarDecl>().size shouldBe 5
|
||||||
stmts.filterIsInstance<Assignment>().size shouldBe 5
|
stmts.filterIsInstance<Assignment>().size shouldBe 5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("correctly process constant prefix numbers with type mismatch and give error") {
|
||||||
|
val src="""
|
||||||
|
main {
|
||||||
|
sub start() {
|
||||||
|
ubyte @shared z1 = - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
val errors = ErrorReporterForTests()
|
||||||
|
compileText(C64Target, optimize=true, src, writeAssembly=false, errors = errors).assertFailure()
|
||||||
|
errors.errors.size shouldBe 2
|
||||||
|
errors.errors[0] shouldContain "type of value BYTE doesn't match target UBYTE"
|
||||||
|
errors.errors[1] shouldContain "value '-1' out of range for unsigned byte"
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
@ -96,7 +96,7 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid
|
|||||||
override fun copy() = PrefixExpression(operator, expression.copy(), position)
|
override fun copy() = PrefixExpression(operator, expression.copy(), position)
|
||||||
override fun constValue(program: Program): NumericLiteralValue? {
|
override fun constValue(program: Program): NumericLiteralValue? {
|
||||||
val constval = expression.constValue(program) ?: return null
|
val constval = expression.constValue(program) ?: return null
|
||||||
return when(operator) {
|
val converted = when(operator) {
|
||||||
"+" -> constval
|
"+" -> constval
|
||||||
"-" -> when (constval.type) {
|
"-" -> when (constval.type) {
|
||||||
in IntegerDatatypes -> NumericLiteralValue.optimalInteger(-constval.number.toInt(), constval.position)
|
in IntegerDatatypes -> NumericLiteralValue.optimalInteger(-constval.number.toInt(), constval.position)
|
||||||
@ -113,6 +113,12 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid
|
|||||||
"not" -> NumericLiteralValue.fromBoolean(constval.number == 0.0, constval.position)
|
"not" -> NumericLiteralValue.fromBoolean(constval.number == 0.0, constval.position)
|
||||||
else -> throw FatalAstException("invalid operator")
|
else -> throw FatalAstException("invalid operator")
|
||||||
}
|
}
|
||||||
|
return if(converted==null)
|
||||||
|
null
|
||||||
|
else {
|
||||||
|
converted.linkParents(this.parent)
|
||||||
|
converted
|
||||||
|
}
|
||||||
}
|
}
|
||||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||||
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
|
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
|
||||||
@ -340,8 +346,11 @@ class TypecastExpression(var expression: Expression, var type: DataType, val imp
|
|||||||
override fun constValue(program: Program): NumericLiteralValue? {
|
override fun constValue(program: Program): NumericLiteralValue? {
|
||||||
val cv = expression.constValue(program) ?: return null
|
val cv = expression.constValue(program) ?: return null
|
||||||
val cast = cv.cast(type)
|
val cast = cv.cast(type)
|
||||||
return if(cast.isValid)
|
return if(cast.isValid) {
|
||||||
cast.valueOrZero()
|
val newval = cast.valueOrZero()
|
||||||
|
newval.linkParents(parent)
|
||||||
|
return newval
|
||||||
|
}
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
@ -725,7 +725,7 @@ class TestProg8Parser: FunSpec( {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xtest("assignment isAugmented correctness") {
|
test("assignment isAugmented correctness") {
|
||||||
val src = SourceCode.Text("""
|
val src = SourceCode.Text("""
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
|
Loading…
Reference in New Issue
Block a user