prog8/compiler/test/ast/TestVarious.kt
2022-11-16 01:39:34 +01:00

166 lines
5.3 KiB
Kotlin

package prog8tests.ast
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.types.instanceOf
import prog8.ast.IFunctionCall
import prog8.ast.expressions.BinaryExpression
import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteral
import prog8.ast.expressions.StringLiteral
import prog8.ast.statements.Assignment
import prog8.ast.statements.InlineAssembly
import prog8.ast.statements.VarDecl
import prog8.code.core.DataType
import prog8.code.core.Position
import prog8.code.target.C64Target
import prog8.compiler.printProgram
import prog8tests.helpers.compileText
class TestVarious: FunSpec({
test("symbol names in inline assembly blocks") {
val names1 = InlineAssembly("""
""", false, Position.DUMMY).names
names1 shouldBe emptySet()
val names2 = InlineAssembly("""
label: lda #<value
sta ${'$'}ea
sta 123
label2:
sta othervalue ; but not these in the comments
; also not these
;; ...or these
// valid words 123456
""", false, Position.DUMMY).names
names2 shouldBe setOf("label", "lda", "sta", "ea", "value", "label2", "othervalue", "valid", "words")
}
test("array literals") {
val text="""
%zeropage basicsafe
main {
sub start() {
ubyte b1
ubyte b2
ubyte[] array1 = [1,2,3]
ubyte[] array2 = [9,8,7]
uword[] @shared addresses1 = [&b1, &b2]
uword[] @shared addresses2 = [array1, array2]
uword[] @shared addresses3 = [&array1, &array2]
uword[] @shared addresses4 = ["string1", "string2"]
uword[] @shared addresses5 = [1111, 2222]
}
}"""
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
}
test("invalid && operator") {
val text="""
main {
sub start() {
uword b1
uword b2
uword b3 = b1 && b2 ; invalid syntax: '&&' is not an operator, 'and' should be used instead
}
}"""
compileText(C64Target(), false, text, writeAssembly = false) shouldBe null
}
test("simple string comparison still works") {
val src="""
main {
sub start() {
ubyte @shared value
str thing = "????"
if thing=="name" {
value++
}
if thing!="name" {
value++
}
}
}"""
val result = compileText(C64Target(), optimize=false, src, writeAssembly=true)!!
val stmts = result.program.entrypoint.statements
stmts.size shouldBe 6
}
test("string concatenation and repeats") {
val src="""
main {
sub start() {
str @shared name = "part1" + "part2"
str @shared rept = "rep"*4
const ubyte times = 3
name = "xx1" + "xx2"
rept = "xyz" * (times+1)
}
}"""
val result = compileText(C64Target(), optimize=false, src, writeAssembly=true)!!
val stmts = result.program.entrypoint.statements
stmts.size shouldBe 6
val name1 = stmts[0] as VarDecl
val rept1 = stmts[1] as VarDecl
(name1.value as StringLiteral).value shouldBe "part1part2"
(rept1.value as StringLiteral).value shouldBe "reprepreprep"
val name2strcopy = stmts[3] as IFunctionCall
val rept2strcopy = stmts[4] as IFunctionCall
val name2 = name2strcopy.args.first() as IdentifierReference
val rept2 = rept2strcopy.args.first() as IdentifierReference
(name2.targetVarDecl(result.program)!!.value as StringLiteral).value shouldBe "xx1xx2"
(rept2.targetVarDecl(result.program)!!.value as StringLiteral).value shouldBe "xyzxyzxyzxyz"
}
test("pointervariable indexing allowed with >255") {
val src="""
main {
sub start() {
uword pointer = ${'$'}2000
@(pointer+${'$'}1000) = 123
ubyte @shared ub = @(pointer+${'$'}1000)
pointer[${'$'}1000] = 99
ub = pointer[${'$'}1000]
uword index = ${'$'}1000
pointer[index] = 55
ub = pointer[index]
}
}"""
compileText(C64Target(), optimize=false, src, writeAssembly=false) shouldNotBe null
}
test("bitshift left of const byte converted to word") {
val src="""
main {
sub start() {
ubyte shift = 10
uword value = 1<<shift
value++
value = 1<<shift
value++
}
}"""
val result = compileText(C64Target(), optimize=false, src, writeAssembly=false)!!
printProgram(result.program)
val stmts = result.program.entrypoint.statements
stmts.size shouldBe 7
val assign1expr = (stmts[3] as Assignment).value as BinaryExpression
val assign2expr = (stmts[5] as Assignment).value as BinaryExpression
assign1expr.operator shouldBe "<<"
val leftval1 = assign1expr.left.constValue(result.program)!!
leftval1.type shouldBe DataType.UWORD
leftval1.number shouldBe 1.0
val leftval2 = assign2expr.left.constValue(result.program)!!
leftval2.type shouldBe DataType.UWORD
leftval2.number shouldBe 1.0
}
})