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.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
import io.kotest.matchers.types.instanceOf
|
||||
import io.kotest.matchers.types.shouldBeSameInstanceAs
|
||||
import prog8.ast.Program
|
||||
@ -16,6 +17,7 @@ import prog8.ast.statements.*
|
||||
import prog8.compiler.BeforeAsmGenerationAstChanger
|
||||
import prog8.compiler.target.C64Target
|
||||
import prog8.compilerinterface.*
|
||||
import prog8tests.helpers.*
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
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 tc = TypecastExpression(number, DataType.BYTE, false, Position.DUMMY)
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
@ -83,9 +85,24 @@ class TestOptimization: FunSpec({
|
||||
tc shouldBeSameInstanceAs number.parent
|
||||
val constvalue = tc.constValue(program)!!
|
||||
constvalue shouldBe instanceOf<NumericLiteralValue>()
|
||||
constvalue.number.toInt() shouldBe 11
|
||||
constvalue.number shouldBe 11.0
|
||||
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") {
|
||||
@ -410,8 +427,8 @@ class TestOptimization: FunSpec({
|
||||
main {
|
||||
sub start() {
|
||||
ubyte @shared z1 = 1
|
||||
ubyte @shared z2 = +1
|
||||
ubyte @shared z3 = ~1
|
||||
ubyte @shared z2 = + 1
|
||||
ubyte @shared z3 = ~ 1
|
||||
ubyte @shared z4 = not 1
|
||||
byte @shared z5 = - 1
|
||||
}
|
||||
@ -423,4 +440,19 @@ class TestOptimization: FunSpec({
|
||||
stmts.filterIsInstance<VarDecl>().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 constValue(program: Program): NumericLiteralValue? {
|
||||
val constval = expression.constValue(program) ?: return null
|
||||
return when(operator) {
|
||||
val converted = when(operator) {
|
||||
"+" -> constval
|
||||
"-" -> when (constval.type) {
|
||||
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)
|
||||
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: 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? {
|
||||
val cv = expression.constValue(program) ?: return null
|
||||
val cast = cv.cast(type)
|
||||
return if(cast.isValid)
|
||||
cast.valueOrZero()
|
||||
return if(cast.isValid) {
|
||||
val newval = cast.valueOrZero()
|
||||
newval.linkParents(parent)
|
||||
return newval
|
||||
}
|
||||
else
|
||||
null
|
||||
}
|
||||
|
@ -725,7 +725,7 @@ class TestProg8Parser: FunSpec( {
|
||||
}
|
||||
|
||||
|
||||
xtest("assignment isAugmented correctness") {
|
||||
test("assignment isAugmented correctness") {
|
||||
val src = SourceCode.Text("""
|
||||
main {
|
||||
sub start() {
|
||||
|
Loading…
Reference in New Issue
Block a user