mirror of
https://github.com/irmen/prog8.git
synced 2026-10-22 05:02:58 +00:00
fix split words arrays on m68k to be not split
This commit is contained in:
1 parent
c7a8e84fd0
commit
8a7922ffcc
45 files changed
+275
-234
No files matched your search
@@ -20,7 +20,7 @@ enum class BaseDataType {
|
||||
ARRAY_SPLITW, // pass by reference, split word layout, subtype is the element type (restricted to word types)
|
||||
POINTER, // typed pointer, subtype is whatever type is pointed to
|
||||
STRUCT_INSTANCE, // the actual instance of a struct (not directly supported in the language yet, but we need its type)
|
||||
ARRAY_POINTER, // array of pointers (uwords), subtype is whatever type each element points to
|
||||
ARRAY_POINTER, // array of pointers (uwords or longs), subtype is whatever type each element points to
|
||||
UNDEFINED;
|
||||
|
||||
|
||||
@@ -85,12 +85,6 @@ val BaseDataType.isIterable get() = this in setOf(BaseDataType.STR, BaseDataTyp
|
||||
val BaseDataType.isPassByRef get() = this.isIterable && !this.isPointer
|
||||
val BaseDataType.isPassByValue get() = !this.isIterable || this.isPointer
|
||||
|
||||
fun DataType.isSplitWordArrayOnTarget(target: ICompilationTarget): Boolean = when(base) {
|
||||
BaseDataType.ARRAY_SPLITW -> true
|
||||
BaseDataType.ARRAY_POINTER -> target.POINTER_MEM_SIZE <= 2u
|
||||
else -> false
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Interface for types that can be used as subtypes in DataType.
|
||||
@@ -190,17 +184,19 @@ class DataType private constructor(
|
||||
return simpletypes.getValue(dt)
|
||||
}
|
||||
|
||||
fun arrayFor(elementDt: BaseDataType, splitwordarray: Boolean=true): DataType {
|
||||
fun arrayFor(elementDt: BaseDataType): DataType {
|
||||
// wether or not a word-array should be split-words, is determined later
|
||||
require(!elementDt.isPointer) { "use other array constructor for arrays of pointers" }
|
||||
val actualElementDt = if(elementDt==BaseDataType.STR) BaseDataType.UWORD else elementDt // array of strings is actually just an array of UWORD pointers
|
||||
return if(splitwordarray && actualElementDt.isWord)
|
||||
DataType(BaseDataType.ARRAY_SPLITW, actualElementDt, null)
|
||||
else {
|
||||
if(actualElementDt.isNumericOrBool)
|
||||
DataType(BaseDataType.ARRAY, actualElementDt, null)
|
||||
else
|
||||
throw NoSuchElementException("invalid basic element dt $elementDt")
|
||||
}
|
||||
if(actualElementDt.isNumericOrBool)
|
||||
return DataType(BaseDataType.ARRAY, actualElementDt, null)
|
||||
else
|
||||
throw NoSuchElementException("invalid basic element dt $elementDt")
|
||||
}
|
||||
|
||||
fun splitWordArrayFor(elementDt: BaseDataType): DataType {
|
||||
require(elementDt.isWord) { "split word array element type must be word" }
|
||||
return DataType(BaseDataType.ARRAY_SPLITW, elementDt, null)
|
||||
}
|
||||
|
||||
fun arrayOfPointersTo(sub: BaseDataType): DataType = DataType(BaseDataType.ARRAY_POINTER, sub, null)
|
||||
@@ -225,8 +221,10 @@ class DataType private constructor(
|
||||
// ============================================================================
|
||||
|
||||
fun elementToArray(splitwords: Boolean = true): DataType {
|
||||
return if (base == BaseDataType.UWORD || base == BaseDataType.WORD || base == BaseDataType.STR) arrayFor(base, splitwords)
|
||||
else arrayFor(base, false)
|
||||
if (splitwords && (base == BaseDataType.UWORD || base == BaseDataType.WORD || base == BaseDataType.STR))
|
||||
return splitWordArrayFor(base)
|
||||
else
|
||||
return arrayFor(base)
|
||||
}
|
||||
|
||||
fun elementType(): DataType =
|
||||
@@ -248,11 +246,14 @@ class DataType private constructor(
|
||||
if (isPointer)
|
||||
return untypedPointerType
|
||||
if (isArray) {
|
||||
if (msb || base == BaseDataType.ARRAY_SPLITW)
|
||||
val isSplit = base == BaseDataType.ARRAY_SPLITW ||
|
||||
(base == BaseDataType.ARRAY_POINTER && mem.memorySize(BaseDataType.POINTER) <= 2)
|
||||
if (msb || isSplit)
|
||||
return pointer(BaseDataType.UBYTE)
|
||||
val elementDt = elementType()
|
||||
require(elementDt.isBasic)
|
||||
return pointer(elementDt)
|
||||
if (elementDt.isBasic)
|
||||
return pointer(elementDt)
|
||||
return untypedPointerType
|
||||
}
|
||||
if (subType != null)
|
||||
return pointer(this)
|
||||
|
||||
@@ -8,6 +8,7 @@ import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import prog8.code.core.*
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for DataType and BaseDataType classes in codeCore.
|
||||
* Focus on type predicates, relationships, and key operations.
|
||||
@@ -98,7 +99,7 @@ class TestDataType: FunSpec({
|
||||
|
||||
test("isSplitWordArray extension") {
|
||||
BaseDataType.ARRAY_SPLITW.isSplitWordArray.shouldBeTrue()
|
||||
BaseDataType.ARRAY_POINTER.isSplitWordArray.shouldBeFalse()
|
||||
BaseDataType.ARRAY_POINTER.isSplitWordArray.shouldBeTrue()
|
||||
BaseDataType.ARRAY.isSplitWordArray.shouldBeFalse()
|
||||
}
|
||||
|
||||
@@ -124,9 +125,9 @@ class TestDataType: FunSpec({
|
||||
ubyteArray.base shouldBe BaseDataType.ARRAY
|
||||
ubyteArray.sub shouldBe BaseDataType.UBYTE
|
||||
|
||||
val wordArraySplit = DataType.arrayFor(BaseDataType.WORD)
|
||||
wordArraySplit.base shouldBe BaseDataType.ARRAY_SPLITW
|
||||
wordArraySplit.sub shouldBe BaseDataType.WORD
|
||||
val wordArray = DataType.arrayFor(BaseDataType.WORD)
|
||||
wordArray.base shouldBe BaseDataType.ARRAY
|
||||
wordArray.sub shouldBe BaseDataType.WORD
|
||||
}
|
||||
|
||||
test("DataType.pointer creates pointer types") {
|
||||
@@ -306,6 +307,6 @@ class TestDataType: FunSpec({
|
||||
|
||||
test("DataType.toString for arrays") {
|
||||
DataType.arrayFor(BaseDataType.UBYTE).toString() shouldBe "ubyte[]"
|
||||
DataType.arrayFor(BaseDataType.WORD).toString() shouldBe "word[] (split)"
|
||||
DataType.arrayFor(BaseDataType.WORD).toString() shouldBe "word[]"
|
||||
}
|
||||
})
|
||||
@@ -1137,7 +1137,7 @@ import prog8.codegen.cpu6502.assignment.*
|
||||
val msbAdd: Int
|
||||
if(indexer.splitWords) {
|
||||
val arrayVariable = indexer.variable ?: TODO("ptr indexing ${indexer.position}")
|
||||
indexer.setChild(0, PtIdentifier(arrayVariable.name + (if(msb) "_msb" else "_lsb"), DataType.arrayFor(BaseDataType.UBYTE, false), arrayVariable.position))
|
||||
indexer.setChild(0, PtIdentifier(arrayVariable.name + (if(msb) "_msb" else "_lsb"), DataType.arrayFor(BaseDataType.UBYTE), arrayVariable.position))
|
||||
elementSize = 1
|
||||
msbAdd = 0
|
||||
} else {
|
||||
|
||||
@@ -7,15 +7,14 @@ import prog8.code.SymbolTable
|
||||
import prog8.code.ast.PtProgram
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8.codegen.cpu6502.*
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.helpers.DummyStringEncoder
|
||||
|
||||
|
||||
class TestAsmOptimizer: FunSpec({
|
||||
|
||||
val machine = C64Target()
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val symbolTable = SymbolTable(program)
|
||||
|
||||
// Add test variables with known non-IO addresses so the optimizer can resolve them
|
||||
|
||||
@@ -12,10 +12,9 @@ import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.code.source.SourceCode
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8.codegen.cpu6502.AsmGen6502
|
||||
import prog8.codegen.cpu6502.VariableAllocator
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.helpers.DummyStringEncoder
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
import java.nio.file.Files
|
||||
import kotlin.io.path.Path
|
||||
@@ -46,8 +45,9 @@ class TestCodegen: FunSpec({
|
||||
// xx += cx16.r0
|
||||
// }
|
||||
//}
|
||||
val compTarget = C64Target()
|
||||
val codegen = AsmGen6502(0)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main",false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
sub.add(PtVariable(
|
||||
@@ -166,7 +166,7 @@ class TestCodegen: FunSpec({
|
||||
}
|
||||
|
||||
test("memory mapped zp var is correctly considered to be zp var") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val st = SymbolTable(program)
|
||||
st.add(StMemVar("zpmemvar", DataType.WORD, 0x20u, null, null))
|
||||
st.add(StMemVar("normalmemvar", DataType.WORD, 0x9000u, null, null))
|
||||
|
||||
@@ -228,7 +228,7 @@ class IRCodeGen(
|
||||
val shadowInit = IRVariableInitializer.Array(initBytes.map { IRStSymbolicReference.Numeric(it.toDouble()) })
|
||||
val shadowVar = IRStStaticVariable(
|
||||
shadowName,
|
||||
DataType.arrayFor(BaseDataType.UBYTE, false),
|
||||
DataType.arrayFor(BaseDataType.UBYTE),
|
||||
shadowInit,
|
||||
initBytes.size.toUInt(),
|
||||
ZeropageWish.NOT_IN_ZEROPAGE,
|
||||
|
||||
@@ -2,15 +2,15 @@ import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import prog8.code.*
|
||||
import prog8.code.StNodeType
|
||||
import prog8.code.SymbolTableMaker
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.code.source.SourceCode
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8.codegen.intermediate.prefixScopedName
|
||||
import prog8.codegen.intermediate.prefixSymbols
|
||||
import prog8.codegen.intermediate.typePrefixChar
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.helpers.DummyStringEncoder
|
||||
|
||||
|
||||
class TestSymbolPrefixer : FunSpec({
|
||||
@@ -59,7 +59,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
// --- full program prefixing tests ---
|
||||
|
||||
test("prefixSymbols prefixes a simple program") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
val varX = PtVariable("x", DataType.UBYTE, ZeropageWish.DONTCARE, 0u, false, null, null, Position.DUMMY)
|
||||
@@ -84,7 +84,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
}
|
||||
|
||||
test("prefixSymbols handles subroutine parameters") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
val param = PtSubroutineParameter("arg", DataType.UBYTE, null, Position.DUMMY)
|
||||
@@ -100,7 +100,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
}
|
||||
|
||||
test("prefixSymbols handles constants") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val constant = PtConstant("SIZE", DataType.UWORD, 100.0, null, Position.DUMMY)
|
||||
block.add(constant)
|
||||
@@ -114,7 +114,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
}
|
||||
|
||||
test("prefixSymbols handles labels") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
val label = PtLabel("mylabel", Position.DUMMY)
|
||||
@@ -130,7 +130,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
}
|
||||
|
||||
test("prefixSymbols handles generated labels without prefixing them") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
val genLabel = PtLabel("p8_label_gen_42", Position.DUMMY)
|
||||
@@ -146,7 +146,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
}
|
||||
|
||||
test("prefixSymbols handles struct declarations") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val struct = PtStructDecl("Point", listOf(
|
||||
PtStructField(DataType.UBYTE, "x", null),
|
||||
@@ -163,7 +163,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
}
|
||||
|
||||
test("prefixSymbols handles asmsub") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val asmsub = PtAsmSub("routine", PtAsmSub.Address(null, null, 0x5000u), setOf(CpuRegister.Y), emptyList(), emptyList(), false, Position.DUMMY)
|
||||
block.add(asmsub)
|
||||
@@ -177,7 +177,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
}
|
||||
|
||||
test("prefixSymbols handles memmapped variables") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val memvar = PtMemMapped("reg", DataType.UBYTE, 0xd020u, null, Position.DUMMY)
|
||||
block.add(memvar)
|
||||
@@ -193,7 +193,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
// --- noSymbolPrefixing tests ---
|
||||
|
||||
test("noSymbolPrefixing blocks keep their names intact") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val libOptions = PtBlock.Options(noSymbolPrefixing = true)
|
||||
val libBlock = PtBlock("lib", false, SourceCode.Generated("test"), libOptions, Position.DUMMY)
|
||||
val libSub = PtSub("func", emptyList(), emptyList(), Position.DUMMY)
|
||||
@@ -209,7 +209,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
}
|
||||
|
||||
test("references from user block to noSymbolPrefixing block are not prefixed") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
|
||||
// Library block with no symbol prefixing
|
||||
val libOptions = PtBlock.Options(noSymbolPrefixing = true)
|
||||
@@ -240,7 +240,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
}
|
||||
|
||||
test("references from noSymbolPrefixing block to regular block get prefixed") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
|
||||
// Regular user block
|
||||
val userBlock = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
@@ -267,7 +267,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
}
|
||||
|
||||
test("identifier references are prefixed according to their target type") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
val varX = PtVariable("x", DataType.UBYTE, ZeropageWish.DONTCARE, 0u, false, null, null, Position.DUMMY)
|
||||
@@ -290,7 +290,7 @@ class TestSymbolPrefixer : FunSpec({
|
||||
}
|
||||
|
||||
test("prefixSymbols exception for unknown identifier") {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
val idRef = PtIdentifier("nonexistent", DataType.UBYTE, Position.DUMMY)
|
||||
|
||||
@@ -12,8 +12,7 @@ import prog8.codegen.vm.VmCodeGen
|
||||
import prog8.intermediate.IRSubroutine
|
||||
import prog8.intermediate.Opcode
|
||||
import prog8.intermediate.toAddress
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.helpers.DummyStringEncoder
|
||||
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
|
||||
class TestVmCodeGen: FunSpec({
|
||||
@@ -41,8 +40,9 @@ class TestVmCodeGen: FunSpec({
|
||||
// xx += cx16.r0
|
||||
// }
|
||||
//}
|
||||
val compTarget = VMTarget()
|
||||
val codegen = VmCodeGen(false)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
sub.add(PtVariable(
|
||||
@@ -153,7 +153,7 @@ class TestVmCodeGen: FunSpec({
|
||||
// Pattern: @(ptr+offset) = @(ptr+offset) + val i.e. ptr[offset] += val
|
||||
// Non-zero offsets are used to avoid potential optimization of the address expression.
|
||||
val codegen = VmCodeGen(false)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
sub.add(PtVariable("ptr", DataType.pointer(BaseDataType.UBYTE), ZeropageWish.DONTCARE, 0u, false, null, null, Position.DUMMY))
|
||||
@@ -230,7 +230,7 @@ class TestVmCodeGen: FunSpec({
|
||||
// }
|
||||
//}
|
||||
val codegen = VmCodeGen(false)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
sub.add(PtVariable(
|
||||
@@ -302,7 +302,7 @@ class TestVmCodeGen: FunSpec({
|
||||
// }
|
||||
//}
|
||||
val codegen = VmCodeGen(false)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
sub.add(PtVariable(
|
||||
@@ -370,7 +370,7 @@ class TestVmCodeGen: FunSpec({
|
||||
// }
|
||||
//}
|
||||
val codegen = VmCodeGen(false)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
sub.add(PtVariable(
|
||||
@@ -426,7 +426,7 @@ class TestVmCodeGen: FunSpec({
|
||||
// }
|
||||
//}
|
||||
val codegen = VmCodeGen(false)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
sub.add(PtVariable(
|
||||
@@ -498,7 +498,7 @@ class TestVmCodeGen: FunSpec({
|
||||
// }
|
||||
//}
|
||||
val codegen = VmCodeGen(false)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
sub.add(PtVariable(
|
||||
@@ -566,7 +566,7 @@ class TestVmCodeGen: FunSpec({
|
||||
// }
|
||||
//}
|
||||
val codegen = VmCodeGen(false)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
sub.add(PtVariable(
|
||||
@@ -615,7 +615,7 @@ class TestVmCodeGen: FunSpec({
|
||||
// }
|
||||
//}
|
||||
val codegen = VmCodeGen(false)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val extsub = PtAsmSub("routine", PtAsmSub.Address(null, null, 0x5000u), setOf(CpuRegister.Y), emptyList(), emptyList(), false, Position.DUMMY)
|
||||
block.add(extsub)
|
||||
@@ -640,7 +640,7 @@ class TestVmCodeGen: FunSpec({
|
||||
|
||||
test("ir codegen for target 'virtual' produces no prefixed names") {
|
||||
val codegen = VmCodeGen(false)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
sub.add(PtVariable("x", DataType.UBYTE, ZeropageWish.DONTCARE, 0u, false, null, null, Position.DUMMY))
|
||||
@@ -668,7 +668,7 @@ class TestVmCodeGen: FunSpec({
|
||||
|
||||
test("ir codegen for target 'cx16' via newcodegen produces prefixed names") {
|
||||
val codegen = VmCodeGen(false)
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
|
||||
val sub = PtSub("start", emptyList(), emptyList(), Position.DUMMY)
|
||||
sub.add(PtVariable("x", DataType.UBYTE, ZeropageWish.DONTCARE, 0u, false, null, null, Position.DUMMY))
|
||||
|
||||
@@ -110,7 +110,7 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors:
|
||||
if (leftPtrConst != null && rightOffsetConst != null) {
|
||||
val ptrDt = leftDt.getOrUndef()
|
||||
val subDt = ptrDt.sub
|
||||
val scale = if(subDt is BaseDataType) program.memsizer.memorySize(subDt) else ptrDt.size(program.memsizer)
|
||||
val scale = if(subDt is BaseDataType) program.target.memorySize(subDt) else ptrDt.size(program.target)
|
||||
val offset = rightOffsetConst.number.toInt() * scale
|
||||
val result = if (expr.operator == "+") leftPtrConst.number + offset else leftPtrConst.number - offset
|
||||
return listOf(AstReplaceNode(expr, NumericLiteral(BaseDataType.UWORD, result, expr.position), parent))
|
||||
@@ -123,7 +123,7 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors:
|
||||
if (rightPtrConst != null && leftOffsetConst != null) {
|
||||
val ptrDt = rightDt.getOrUndef()
|
||||
val subDt = ptrDt.sub
|
||||
val scale = if(subDt is BaseDataType) program.memsizer.memorySize(subDt) else ptrDt.size(program.memsizer)
|
||||
val scale = if(subDt is BaseDataType) program.target.memorySize(subDt) else ptrDt.size(program.target)
|
||||
val offset = leftOffsetConst.number.toInt() * scale
|
||||
val result = rightPtrConst.number + offset
|
||||
return listOf(AstReplaceNode(expr, NumericLiteral(BaseDataType.UWORD, result, expr.position), parent))
|
||||
@@ -142,8 +142,8 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors:
|
||||
val concatenated = if(leftString.encoding==rightString.encoding) {
|
||||
leftString.value + rightString.value
|
||||
} else {
|
||||
program.encoding.decodeString(
|
||||
program.encoding.encodeString(leftString.value, leftString.encoding) + program.encoding.encodeString(rightString.value, rightString.encoding),
|
||||
program.target.decodeString(
|
||||
program.target.encodeString(leftString.value, leftString.encoding) + program.target.encodeString(rightString.value, rightString.encoding),
|
||||
leftString.encoding)
|
||||
}
|
||||
val concatStr = StringLiteral.create(concatenated, leftString.encoding, expr.position)
|
||||
@@ -535,7 +535,7 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors:
|
||||
|
||||
override fun after(decl: VarDecl, parent: Node): Iterable<AstModification> {
|
||||
if (decl.type == VarDeclType.CONST && decl.datatype.isPointer) {
|
||||
val sizer = program.memsizer
|
||||
val sizer = program.target
|
||||
if (decl.datatype.size(sizer) > 1) {
|
||||
errors.err("due to internal compiler complexity, currently pointer variables with data type size > 1 cannot be const", decl.position)
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ class VarConstantValueTypeAdjuster(
|
||||
|
||||
private fun canBeMadeConst(decl: VarDecl, usages: List<Node>): Boolean {
|
||||
if (decl.datatype.isPointer) {
|
||||
if (decl.datatype.size(program.memsizer) > 1) return false
|
||||
if (decl.datatype.size(program.target) > 1) return false
|
||||
val derefCount = usages.count {
|
||||
val p = it.parent
|
||||
val gp = p.parent
|
||||
@@ -599,7 +599,7 @@ internal class ConstantIdentifierReplacer(
|
||||
if(declArraySize!=null && declArraySize!=rangeExpr.size())
|
||||
errors.err("range expression size (${rangeExpr.size()}) doesn't match declared array size ($declArraySize)", decl.value?.position!!)
|
||||
if(constRange!=null) {
|
||||
return ArrayLiteral(InferredTypes.InferredType.known(DataType.arrayFor(BaseDataType.FLOAT, false)),
|
||||
return ArrayLiteral(InferredTypes.InferredType.known(DataType.arrayFor(BaseDataType.FLOAT)),
|
||||
constRange.map { NumericLiteral(BaseDataType.FLOAT, it.toDouble(), decl.value!!.position) }.toTypedArray(),
|
||||
position = decl.value!!.position)
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ sys {
|
||||
|
||||
; ------- memory routines --------
|
||||
|
||||
asmsub memcopy(^^ubyte source @D0, ^^ubyte tgt @D1, uword count @D2) {
|
||||
asmsub memcopy(long source @D0, long tgt @D1, uword count @D2) {
|
||||
; Copy bytes from source to target.
|
||||
; Bulk of the work uses long-aligned longword copies;
|
||||
; pre-alignment and remainder bytes use individual byte copies.
|
||||
@@ -186,7 +186,7 @@ sys {
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub memset(^^ubyte mem @D0, uword numbytes @D1, ubyte value @D2) {
|
||||
asmsub memset(long mem @D0, uword numbytes @D1, ubyte value @D2) {
|
||||
%asm {{
|
||||
movea.l d0,a0
|
||||
tst.w d1
|
||||
@@ -237,7 +237,7 @@ sys {
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub memclear(^^ubyte mem @D0, uword numbytes @D1) {
|
||||
asmsub memclear(long mem @D0, uword numbytes @D1) {
|
||||
; Clear memory (fill with zero). Uses movem.l d0-d7,-(a0)
|
||||
; for the bulk clear (32 bytes per instruction, decrementing from
|
||||
; the end address). Handles misaligned start and remaining bytes.
|
||||
@@ -314,7 +314,7 @@ sys {
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub memsetw(^^ubyte mem @D0, uword numwords @D1, uword value @D2) {
|
||||
asmsub memsetw(long mem @D0, uword numwords @D1, uword value @D2) {
|
||||
; Fill memory with the given 16-bit word value, for the given number of words.
|
||||
; Word-aligned start: fast path with longword stores (2 words at a time).
|
||||
; Odd start: first byte written individually to realign, then same fast path
|
||||
|
||||
@@ -123,7 +123,7 @@ private fun builtinOffsetof(args: List<Expression>, position: Position, program:
|
||||
val structname = identifier.dropLast(1)
|
||||
val fieldname = identifier.last()
|
||||
val struct = args[0].definingScope.lookup(structname) as? StructDecl ?: throw SyntaxError("cannot find struct '$structname'", args[0].position)
|
||||
val offset = struct.offsetof(fieldname, program.memsizer) ?: throw SyntaxError("no such field '${identifier.joinToString(".")}'", args[0].position)
|
||||
val offset = struct.offsetof(fieldname, program.target) ?: throw SyntaxError("no such field '${identifier.joinToString(".")}'", args[0].position)
|
||||
return NumericLiteral.optimalInteger(offset.toInt(), position)
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ private fun builtinSizeof(args: List<Expression>, position: Position, program: P
|
||||
val dt = args[0].inferType(program)
|
||||
if(dt.isKnown) {
|
||||
if(args[0] is NumericLiteral || args[0] is AddressOf || args[0] is MemorySlabRef)
|
||||
return NumericLiteral.optimalInteger(program.memsizer.memorySize(dt.getOrUndef(), null), position)
|
||||
return NumericLiteral.optimalInteger(program.target.memorySize(dt.getOrUndef(), null), position)
|
||||
|
||||
val target = (args[0] as? IdentifierReference)?.targetStatement()
|
||||
?: throw SyntaxError("wrong argument type", position)
|
||||
@@ -146,7 +146,7 @@ private fun builtinSizeof(args: List<Expression>, position: Position, program: P
|
||||
dt.isArray -> {
|
||||
val length = (target as VarDecl).arraysize?.constIndex() ?: throw CannotEvaluateException("sizeof", "unknown array size")
|
||||
val elementDt = dt.getOrUndef().elementType()
|
||||
NumericLiteral.optimalInteger(program.memsizer.memorySize(elementDt, length), position)
|
||||
NumericLiteral.optimalInteger(program.target.memorySize(elementDt, length), position)
|
||||
}
|
||||
dt.isString -> {
|
||||
if(target is VarDecl) {
|
||||
@@ -156,26 +156,26 @@ private fun builtinSizeof(args: List<Expression>, position: Position, program: P
|
||||
else
|
||||
throw SyntaxError("sizeof(str) is undefined here. Perhaps use len, or strings.length?", position)
|
||||
}
|
||||
else -> NumericLiteral.optimalInteger( program.memsizer.memorySize(dt.getOrUndef(), null), position)
|
||||
else -> NumericLiteral.optimalInteger( program.target.memorySize(dt.getOrUndef(), null), position)
|
||||
}
|
||||
} else {
|
||||
val identifier = args[0] as? IdentifierReference
|
||||
if(identifier?.nameInSource?.size==1) {
|
||||
when(identifier.nameInSource[0]) {
|
||||
"ubyte" -> return NumericLiteral.optimalInteger(program.memsizer.memorySize(BaseDataType.UBYTE), position)
|
||||
"byte" -> return NumericLiteral.optimalInteger(program.memsizer.memorySize(BaseDataType.BYTE), position)
|
||||
"uword" -> return NumericLiteral.optimalInteger(program.memsizer.memorySize(BaseDataType.UWORD), position)
|
||||
"word" -> return NumericLiteral.optimalInteger(program.memsizer.memorySize(BaseDataType.WORD), position)
|
||||
"long" -> return NumericLiteral.optimalInteger(program.memsizer.memorySize(BaseDataType.LONG), position)
|
||||
"float" -> return NumericLiteral.optimalInteger(program.memsizer.memorySize(BaseDataType.FLOAT), position)
|
||||
"bool" -> return NumericLiteral.optimalInteger(program.memsizer.memorySize(BaseDataType.BOOL), position)
|
||||
"ubyte" -> return NumericLiteral.optimalInteger(program.target.memorySize(BaseDataType.UBYTE), position)
|
||||
"byte" -> return NumericLiteral.optimalInteger(program.target.memorySize(BaseDataType.BYTE), position)
|
||||
"uword" -> return NumericLiteral.optimalInteger(program.target.memorySize(BaseDataType.UWORD), position)
|
||||
"word" -> return NumericLiteral.optimalInteger(program.target.memorySize(BaseDataType.WORD), position)
|
||||
"long" -> return NumericLiteral.optimalInteger(program.target.memorySize(BaseDataType.LONG), position)
|
||||
"float" -> return NumericLiteral.optimalInteger(program.target.memorySize(BaseDataType.FLOAT), position)
|
||||
"bool" -> return NumericLiteral.optimalInteger(program.target.memorySize(BaseDataType.BOOL), position)
|
||||
}
|
||||
}
|
||||
|
||||
// the argument could refer to a struct declaration
|
||||
val struct = (args[0] as? IdentifierReference)?.targetStructDecl()
|
||||
if(struct!=null) {
|
||||
val size = struct.memsize(program.memsizer)
|
||||
val size = struct.memsize(program.target)
|
||||
return NumericLiteral(BaseDataType.UBYTE, size.toDouble(), position)
|
||||
}
|
||||
|
||||
|
||||
@@ -412,7 +412,7 @@ fun parseMainModule(filepath: Path,
|
||||
quiet: Boolean,
|
||||
traceImports: Boolean): Triple<Program, CompilationOptions, List<Path>> {
|
||||
val bf = BuiltinFunctionsFacade(BuiltinFunctions)
|
||||
val program = Program(filepath.nameWithoutExtension, bf, compTarget, compTarget)
|
||||
val program = Program(filepath.nameWithoutExtension, bf, compTarget)
|
||||
bf.program = program
|
||||
|
||||
val importer = ModuleImporter(program, compTarget.name, errors, sourceDirs, libraryDirs, cwd, quiet, traceImports)
|
||||
|
||||
@@ -1698,6 +1698,8 @@ internal class AstChecker(private val program: Program,
|
||||
// exception allowed on 16 bits pointers: comparing uword (pointer) with string
|
||||
} else if(compilerOptions.compTarget.POINTER_MEM_SIZE>2u && leftDt.isPointer && rightDt.isString) {
|
||||
// exception allowed on 32 bits pointers: comparing pointer with string
|
||||
} else if(compilerOptions.compTarget.POINTER_MEM_SIZE>2u && ((leftDt.isLong && rightDt.isPointer) || (leftDt.isPointer && rightDt.isLong))) {
|
||||
// exception allowed on 32 bits pointers: comparing long (untyped pointer) with pointer
|
||||
} else {
|
||||
errors.err("left and right operands aren't the same type: $leftDt vs $rightDt", expr.position)
|
||||
}
|
||||
@@ -2310,7 +2312,7 @@ internal class AstChecker(private val program: Program,
|
||||
val uniqueFields = struct.fields.mapTo(mutableSetOf()) { it.name }
|
||||
if(uniqueFields.size!=struct.fields.size)
|
||||
errors.err("duplicate field names in struct", struct.position)
|
||||
val memsize = struct.memsize(program.memsizer)
|
||||
val memsize = struct.memsize(program.target)
|
||||
if(memsize>256)
|
||||
errors.err("struct contains too many fields, max struct size is 256 bytes (actual: $memsize)", struct.position)
|
||||
|
||||
@@ -2642,7 +2644,7 @@ internal class AstChecker(private val program: Program,
|
||||
targetDatatype.isUnsignedByte -> sourceDatatype.isUnsignedByte
|
||||
targetDatatype.isSignedWord -> sourceDatatype.isSignedWord || sourceDatatype.isByte
|
||||
targetDatatype.isUnsignedWord -> sourceDatatype.isUnsignedWord || sourceDatatype.isUnsignedByte
|
||||
targetDatatype.isLong -> sourceDatatype.isLong || sourceDatatype.isWord || sourceDatatype.isByte
|
||||
targetDatatype.isLong -> sourceDatatype.isLong || sourceDatatype.isPointer || sourceDatatype.isWord || sourceDatatype.isByte
|
||||
targetDatatype.isFloat -> sourceDatatype.isNumeric
|
||||
targetDatatype.isString -> sourceDatatype.isString
|
||||
else -> false
|
||||
@@ -2668,9 +2670,9 @@ internal class AstChecker(private val program: Program,
|
||||
errors.err("cannot assign different pointer type, expected $targetDatatype or uword but got $sourceDatatype", position)
|
||||
} else if(sourceDatatype.isString && targetDatatype.sub?.isByte==true) {
|
||||
// assigning a string to a byte pointer is allowed.
|
||||
} else if(!sourceDatatype.isUnsignedWord && !sourceDatatype.isStructInstance)
|
||||
} else if(!sourceDatatype.isUnsignedWord && !sourceDatatype.isLong && !sourceDatatype.isStructInstance)
|
||||
if(!(sourceDatatype isAssignableTo targetDatatype))
|
||||
errors.err("incompatible value type, can only assign uword or correct pointer type", position)
|
||||
errors.err("incompatible value type, can only assign uword, long, or correct pointer type", position)
|
||||
}
|
||||
else if(targetDatatype.isString && sourceDatatype.isUnsignedWord)
|
||||
errors.err("can't assign uword to str. If the source is a string pointer and you actually want to overwrite the target string, use an explicit strings.copy(src,tgt) instead.", position)
|
||||
|
||||
@@ -161,7 +161,7 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
|
||||
if(options.compTarget.name != VMTarget.NAME && expr.left.inferType(program).isPointer) {
|
||||
val cast = expr.right as? TypecastExpression
|
||||
if(cast!=null && cast.type.isWord && cast.expression.inferType(program).isBytes) {
|
||||
val structsize = expr.left.inferType(program).getOrUndef().size(program.memsizer)
|
||||
val structsize = expr.left.inferType(program).getOrUndef().size(program.target)
|
||||
// pointer + byte -> (pointer as uword) + (byte as uword * structsize) (yields better code on 6502 than the plain pointer arithmetic)
|
||||
// but only if the struct/value size is >1
|
||||
if(structsize>1) {
|
||||
|
||||
@@ -789,7 +789,7 @@ _after:
|
||||
true // for calls (indirect JSR), split array is always the optimal choice
|
||||
else
|
||||
target.cpu==CpuType.CPU6502 // for goto (indirect JMP), split array is optimal for 6502, but NOT for the 65C02 (it has a different JMP addressing mode available)
|
||||
val arrayDt = DataType.arrayFor(BaseDataType.UWORD, split)
|
||||
val arrayDt = DataType.arrayFor(BaseDataType.UWORD)
|
||||
val labelArray = ArrayLiteral(InferredTypes.knownFor(arrayDt), ongoto.labels.toTypedArray(), ongoto.position)
|
||||
val jumplistArray = VarDecl.createAutoOptionalSplit(labelArray)
|
||||
|
||||
@@ -978,13 +978,13 @@ _after:
|
||||
val ptrVar = deref.definingScope.lookup(ptrName) as? VarDecl
|
||||
if(ptrVar!=null && (ptrVar.datatype.isPointer || ptrVar.datatype.isPointerArray)) {
|
||||
val struct = ptrVar.datatype.subType!! as StructDecl
|
||||
val offsetNumber = NumericLiteral.optimalInteger(struct.offsetof(field.first, program.memsizer)!!.toInt(), deref.position)
|
||||
val offsetNumber = NumericLiteral.optimalInteger(struct.offsetof(field.first, program.target)!!.toInt(), deref.position)
|
||||
val pointerIdentifier = IdentifierReference(ptrName, deref.position)
|
||||
val addrType = if(target.POINTER_MEM_SIZE > 2u) DataType.LONG else DataType.UWORD
|
||||
val address: Expression
|
||||
if(ptrVar.datatype.isPointer) {
|
||||
// pointer[idx].field = value --> pokeXXX(pointer as uword/long + idx*sizeof(Struct) + offsetof(Struct.field), value)
|
||||
val structSize = ptrVar.datatype.dereference().size(program.memsizer)
|
||||
val structSize = ptrVar.datatype.dereference().size(program.target)
|
||||
val pointerAsAddr = TypecastExpression(pointerIdentifier, addrType, true, deref.position)
|
||||
val idx = ptr.last().second!!.indexExpr
|
||||
val scaledIndex = BinaryExpression(idx, "*", NumericLiteral(BaseDataType.UWORD, structSize.toDouble(), deref.position), deref.position)
|
||||
@@ -1162,7 +1162,7 @@ _after:
|
||||
if(targetDt.isStructInstance && sourceDt.isStructInstance) {
|
||||
if(targetDt == sourceDt) {
|
||||
// special case simple struct instance assignment via memory copy
|
||||
val size = program.memsizer.memorySize(sourceDt.getOrUndef(), null)
|
||||
val size = program.target.memorySize(sourceDt.getOrUndef(), null)
|
||||
val structSizeNum = NumericLiteral.optimalInteger(size, assignment.position)
|
||||
val deref = assignment.value as? PtrDereference
|
||||
if(deref!=null) {
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ internal class LiteralsToAutoVarsAndRecombineIdentifiers(private val program: Pr
|
||||
// turn the array literal it into an identifier reference
|
||||
val litval2 = array.cast(targetDt.getOrUndef())
|
||||
if (litval2 != null) {
|
||||
val vardecl2 = VarDecl.createAuto(litval2)
|
||||
val vardecl2 = VarDecl.createAuto(litval2, program.target)
|
||||
val identifier = IdentifierReference(listOf(vardecl2.name), vardecl2.position)
|
||||
return listOf(
|
||||
AstReplaceNode(array, identifier, parent),
|
||||
|
||||
@@ -85,7 +85,7 @@ internal class M68kAstChecker(private val errors: IErrorReporter) : IAstVisitor
|
||||
if (decl.splitwordarray == SplitWish.NOSPLIT) {
|
||||
errors.err("@nosplit is not available on the m68k target (there are no split word arrays)", decl.position)
|
||||
}
|
||||
if (decl.datatype.isSplitWordArray) {
|
||||
if (decl.datatype.isSplitWordArray && decl.splitwordarray != SplitWish.DONTCARE) {
|
||||
errors.err("split word arrays are not supported on the m68k target", decl.position)
|
||||
}
|
||||
decl.value?.accept(this)
|
||||
|
||||
@@ -42,8 +42,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
|
||||
val ptProgram = PtProgram(
|
||||
program.name,
|
||||
program.memsizer,
|
||||
program.encoding
|
||||
program.target
|
||||
)
|
||||
|
||||
// note: modules are not represented any longer in this Ast. All blocks have been moved into the top scope.
|
||||
@@ -272,7 +271,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
// pointer arithmetic: add or subract the size of the struct times the argument
|
||||
val leftDt = expr.left.inferType(program).getOrUndef()
|
||||
require(leftDt.isPointer && !expr.right.inferType(program).isPointer)
|
||||
val structSize = leftDt.size(program.memsizer)
|
||||
val structSize = leftDt.size(program.target)
|
||||
val constValue = augmentedValue.constValue(program)
|
||||
if(constValue!=null) {
|
||||
val total = constValue.number*structSize
|
||||
@@ -991,7 +990,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
val offsType = addrType.base // use the target-appropriate offset type (UWORD on 6502, LONG on m68k)
|
||||
|
||||
if(leftDt.isPointer && !rightDt.isPointer) {
|
||||
val structSize = leftDt.size(program.memsizer)
|
||||
val structSize = leftDt.size(program.target)
|
||||
val constValue = expr.right.constValue(program)
|
||||
if(constValue!=null) {
|
||||
// ptr + constvalue * structsize
|
||||
@@ -1032,7 +1031,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
}
|
||||
}
|
||||
} else if(!leftDt.isPointer && rightDt.isPointer) {
|
||||
val structSize = rightDt.size(program.memsizer)
|
||||
val structSize = rightDt.size(program.target)
|
||||
val constValue = expr.left.constValue(program)
|
||||
if(constValue!=null) {
|
||||
// ptr + constvalue * structsize
|
||||
@@ -1176,8 +1175,8 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
if(type.isSplitWordArray) {
|
||||
// ranges are never a split word array!
|
||||
when(type.sub) {
|
||||
BaseDataType.WORD -> type = DataType.arrayFor(BaseDataType.WORD, false)
|
||||
BaseDataType.UWORD -> type = DataType.arrayFor(BaseDataType.UWORD, false)
|
||||
BaseDataType.WORD -> type = DataType.arrayFor(BaseDataType.WORD)
|
||||
BaseDataType.UWORD -> type = DataType.arrayFor(BaseDataType.UWORD)
|
||||
else -> { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
paramsPossibleDatatypes = BuiltinFunctions.getValue(sub.name).parameters.map {
|
||||
it.possibleDatatypes.map { dt ->
|
||||
if(dt.isArray)
|
||||
DataType.arrayFor(BaseDataType.BOOL, false) // the builtin function signature doesn't tell us the element type....
|
||||
DataType.arrayFor(BaseDataType.BOOL) // the builtin function signature doesn't tell us the element type....
|
||||
else if(dt.isPointer)
|
||||
DataType.pointer(BaseDataType.UBYTE)
|
||||
else
|
||||
|
||||
@@ -31,7 +31,9 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
VarDeclType.VAR -> {
|
||||
if(decl.isArray) {
|
||||
// using a array of words as initializer to a pointer array is fine
|
||||
if (!valueDt.isSplitWordArray || !decl.datatype.isPointerArray)
|
||||
val ok = valueDt.isSplitWordArray && decl.datatype.isPointerArray ||
|
||||
valueDt.isWordArray && decl.datatype.isPointerArray && decl.splitwordarray == SplitWish.DONTCARE && options.compTarget.POINTER_MEM_SIZE == 2u
|
||||
if (!ok)
|
||||
errors.err("value has incompatible type ($valueType) for the variable (${decl.datatype})", decl.value!!.position)
|
||||
} else if(!decl.datatype.isString) {
|
||||
if (valueDt.largerSizeThan(decl.datatype)) {
|
||||
@@ -87,17 +89,24 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
var changeDataType: DataType?
|
||||
when(decl.splitwordarray) {
|
||||
SplitWish.DONTCARE -> {
|
||||
changeDataType = if(decl.datatype.isSplitWordArray) null else {
|
||||
changeDataType = if(decl.datatype.isSplitWordArray) {
|
||||
if(options.compTarget.POINTER_MEM_SIZE > 2u)
|
||||
DataType.arrayFor(decl.datatype.elementType().base)
|
||||
else
|
||||
null
|
||||
} else {
|
||||
val eltDt = decl.datatype.elementType()
|
||||
if(eltDt.isPointer)
|
||||
TODO("convert array of pointers to split words array type ${decl.position}")
|
||||
else if(options.compTarget.POINTER_MEM_SIZE == 2u)
|
||||
DataType.splitWordArrayFor(eltDt.base)
|
||||
else
|
||||
DataType.arrayFor(eltDt.base)
|
||||
null
|
||||
}
|
||||
}
|
||||
SplitWish.NOSPLIT -> {
|
||||
changeDataType = if(decl.datatype.isSplitWordArray && !decl.datatype.elementType().isPointer)
|
||||
DataType.arrayFor(decl.datatype.elementType().base, false)
|
||||
DataType.arrayFor(decl.datatype.elementType().base)
|
||||
else null
|
||||
}
|
||||
}
|
||||
@@ -116,7 +125,21 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
|
||||
// handle @nosplit on pointer arrays: convert to regular non-split word array
|
||||
if(decl.datatype.isPointerArray && decl.splitwordarray == SplitWish.NOSPLIT) {
|
||||
val newDt = DataType.arrayFor(BaseDataType.UWORD, false) // false = not split (sequential)
|
||||
val newDt = DataType.arrayFor(BaseDataType.UWORD) // non-split
|
||||
var value = decl.value
|
||||
if(value is ArrayLiteral && !(value.type istype newDt)) {
|
||||
value = ArrayLiteral(InferredTypes.knownFor(newDt), value.value, value.position)
|
||||
}
|
||||
val newDecl = VarDecl.builder(newDt, decl.position)
|
||||
.copyFrom(decl)
|
||||
.value(value)
|
||||
.build()
|
||||
return listOf(AstReplaceNode(decl, newDecl, parent))
|
||||
}
|
||||
|
||||
// handle DONTCARE pointer arrays on non-6502 targets: convert back to regular array with long elements
|
||||
if(decl.datatype.isPointerArray && decl.splitwordarray == SplitWish.DONTCARE && options.compTarget.POINTER_MEM_SIZE > 2u) {
|
||||
val newDt = DataType.arrayFor(BaseDataType.LONG)
|
||||
var value = decl.value
|
||||
if(value is ArrayLiteral && !(value.type istype newDt)) {
|
||||
value = ArrayLiteral(InferredTypes.knownFor(newDt), value.value, value.position)
|
||||
@@ -438,7 +461,7 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
if(stringVal.value.isEmpty())
|
||||
return replaceWithFalse()
|
||||
if(stringVal.value.length==1) {
|
||||
val string = program.encoding.encodeString(stringVal.value, stringVal.encoding)
|
||||
val string = program.target.encodeString(stringVal.value, stringVal.encoding)
|
||||
return replaceWithEquals(NumericLiteral(BaseDataType.UBYTE, string[0].toDouble(), stringVal.position))
|
||||
}
|
||||
return noModifications
|
||||
|
||||
@@ -122,6 +122,14 @@ internal class VerifyFunctionArgTypes(val program: Program, val options: Compila
|
||||
if(paramDt.isPointer && argDt.base==BaseDataType.LONG)
|
||||
return true
|
||||
|
||||
// if expected is LONG and actual is an array, we allow it (address of array is a long on 32-bit targets)
|
||||
if(paramDt.isLong && argDt.isArray)
|
||||
return true
|
||||
|
||||
// if expected is LONG and actual is any pointer, we allow it (pointer is a long on m68k)
|
||||
if(paramDt.isLong && argDt.isPointer)
|
||||
return true
|
||||
|
||||
if(paramDt.isString && (argDt.isPointer && argDt.sub==BaseDataType.UBYTE))
|
||||
return true
|
||||
|
||||
|
||||
@@ -19,7 +19,9 @@ import prog8.code.target.VMTarget
|
||||
import prog8.compiler.CallGraph
|
||||
import prog8.parser.Prog8Parser.parseModule
|
||||
import prog8.vm.VmRunner
|
||||
import prog8tests.helpers.*
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
import prog8tests.helpers.compileText
|
||||
import kotlin.io.path.readText
|
||||
|
||||
class TestCallgraph: FunSpec({
|
||||
@@ -166,7 +168,7 @@ class TestCallgraph: FunSpec({
|
||||
}
|
||||
}"""
|
||||
val module = parseModule(SourceCode.Text(source))
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val program = Program("test", DummyFunctions, VMTarget())
|
||||
program.addModule(module)
|
||||
val callgraph = CallGraph(program)
|
||||
val blockMain = program.allBlocks.single { it.name=="main" }
|
||||
@@ -201,7 +203,7 @@ class TestCallgraph: FunSpec({
|
||||
}
|
||||
}"""
|
||||
val module = parseModule(SourceCode.Text(source))
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val program = Program("test", DummyFunctions, VMTarget())
|
||||
program.addModule(module)
|
||||
val callgraph = CallGraph(program)
|
||||
val errors = ErrorReporterForTests()
|
||||
@@ -225,7 +227,7 @@ class TestCallgraph: FunSpec({
|
||||
}
|
||||
}"""
|
||||
val module = parseModule(SourceCode.Text(source))
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val program = Program("test", DummyFunctions, VMTarget())
|
||||
program.addModule(module)
|
||||
val callgraph = CallGraph(program)
|
||||
val errors = ErrorReporterForTests()
|
||||
|
||||
+15
-11
@@ -14,10 +14,14 @@ import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.expressions.PrefixExpression
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.core.*
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.source.SourceCode
|
||||
import prog8.code.target.*
|
||||
import prog8tests.helpers.*
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
import prog8tests.helpers.compileText
|
||||
|
||||
|
||||
class TestMemory: FunSpec({
|
||||
@@ -26,7 +30,7 @@ class TestMemory: FunSpec({
|
||||
val outputDir = tempdir().toPath()
|
||||
|
||||
fun wrapWithProgram(statements: List<Statement>): Program {
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val program = Program("test", DummyFunctions, c64target)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, false, statements.toMutableList(), Position.DUMMY)
|
||||
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
|
||||
program.addModule(module)
|
||||
@@ -271,7 +275,7 @@ class TestMemory: FunSpec({
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
|
||||
Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
Program("test", DummyFunctions, c64target)
|
||||
.addModule(module)
|
||||
target.isIOAddress(c64target) shouldBe false
|
||||
}
|
||||
@@ -294,7 +298,7 @@ class TestMemory: FunSpec({
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
|
||||
Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
Program("test", DummyFunctions, c64target)
|
||||
.addModule(module)
|
||||
target.isIOAddress(c64target) shouldBe false
|
||||
}
|
||||
@@ -317,7 +321,7 @@ class TestMemory: FunSpec({
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
|
||||
Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
Program("test", DummyFunctions, c64target)
|
||||
.addModule(module)
|
||||
target.isIOAddress(c64target) shouldBe true
|
||||
}
|
||||
@@ -331,7 +335,7 @@ class TestMemory: FunSpec({
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
|
||||
Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
Program("test", DummyFunctions, c64target)
|
||||
.addModule(module)
|
||||
target.isIOAddress(c64target) shouldBe false
|
||||
}
|
||||
@@ -348,7 +352,7 @@ class TestMemory: FunSpec({
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
|
||||
Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
Program("test", DummyFunctions, c64target)
|
||||
.addModule(module)
|
||||
target.isIOAddress(c64target) shouldBe false
|
||||
}
|
||||
@@ -365,7 +369,7 @@ class TestMemory: FunSpec({
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
val module = Module(mutableListOf(subroutine), Position.DUMMY, SourceCode.Generated("test"))
|
||||
Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
Program("test", DummyFunctions, c64target)
|
||||
.addModule(module)
|
||||
target.isIOAddress(c64target) shouldBe true
|
||||
}
|
||||
@@ -421,8 +425,8 @@ class TestMemory: FunSpec({
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.UWORD), 10) shouldBe 20
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.LONG), 10) shouldBe 40
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.FLOAT), 10) shouldBe 10*target.FLOAT_MEM_SIZE.toInt()
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.WORD, true), 10) shouldBe 20
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.UWORD, true), 10) shouldBe 20
|
||||
target.memorySize(DataType.splitWordArrayFor(BaseDataType.WORD), 10) shouldBe 20
|
||||
target.memorySize(DataType.splitWordArrayFor(BaseDataType.UWORD), 10) shouldBe 20
|
||||
|
||||
target.memorySize(DataType.BOOL, 10) shouldBe 10
|
||||
target.memorySize(DataType.UWORD, 10) shouldBe 20
|
||||
|
||||
@@ -13,6 +13,7 @@ import prog8.code.INTERNED_STRINGS_MODULENAME
|
||||
import prog8.code.PROG8_CONTAINER_MODULES
|
||||
import prog8.code.core.IErrorReporter
|
||||
import prog8.code.source.SourceCode
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8.compiler.ModuleImporter
|
||||
import prog8.parser.MultipleParseErrors
|
||||
import prog8tests.helpers.*
|
||||
@@ -25,7 +26,7 @@ class TestModuleImporter: FunSpec({
|
||||
lateinit var program: Program
|
||||
|
||||
beforeTest {
|
||||
program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
program = Program("foo", DummyFunctions, VMTarget())
|
||||
}
|
||||
|
||||
fun makeImporter(errors: IErrorReporter? = null, searchIn: Iterable<String>) =
|
||||
|
||||
@@ -23,7 +23,9 @@ import prog8.code.target.C64Target
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8.vm.VmRunner
|
||||
import prog8tests.helpers.*
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
import prog8tests.helpers.compileText
|
||||
import kotlin.io.path.readText
|
||||
|
||||
|
||||
@@ -141,9 +143,10 @@ other {
|
||||
}
|
||||
|
||||
test("generated constvalue from typecast inherits proper parent linkage") {
|
||||
val target = VMTarget()
|
||||
val number = NumericLiteral(BaseDataType.UBYTE, 11.0, Position.DUMMY)
|
||||
val tc = TypecastExpression(number, DataType.BYTE, false, Position.DUMMY)
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val program = Program("test", DummyFunctions, target)
|
||||
tc.linkParents(ParentSentinel)
|
||||
tc.parent shouldNotBe null
|
||||
number.parent shouldNotBe null
|
||||
@@ -156,9 +159,10 @@ other {
|
||||
}
|
||||
|
||||
test("generated constvalue from prefixexpr inherits proper parent linkage") {
|
||||
val target = VMTarget()
|
||||
val number = NumericLiteral(BaseDataType.UBYTE, 11.0, Position.DUMMY)
|
||||
val pfx = PrefixExpression("-", number, Position.DUMMY)
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val program = Program("test", DummyFunctions, target)
|
||||
pfx.linkParents(ParentSentinel)
|
||||
pfx.parent shouldNotBe null
|
||||
number.parent shouldNotBe null
|
||||
|
||||
@@ -662,7 +662,7 @@ main {
|
||||
compileText(VMTarget(), false, src, outputDir, errors=errors)
|
||||
val err = errors.errors
|
||||
err.size shouldBe 1
|
||||
err[0] shouldContain("15:16: incompatible value type, can only assign uword or correct pointer")
|
||||
err[0] shouldContain("15:16: incompatible value type, can only assign uword")
|
||||
}
|
||||
|
||||
test("pointer uword assignments with cast") {
|
||||
@@ -757,12 +757,12 @@ main {
|
||||
DataType.UNDEFINED.typeForUntypedAddressOf(false, memsizer) shouldBe DataType.UWORD
|
||||
DataType.UNDEFINED.typeForUntypedAddressOf(true, memsizer) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||
DataType.STR.typeForUntypedAddressOf(false, memsizer) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||
DataType.arrayFor(BaseDataType.FLOAT, false).typeForUntypedAddressOf(false, memsizer) shouldBe DataType.pointer(BaseDataType.FLOAT)
|
||||
DataType.arrayFor(BaseDataType.FLOAT, false).typeForUntypedAddressOf(true, memsizer) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||
DataType.arrayFor(BaseDataType.UWORD, false).typeForUntypedAddressOf(false, memsizer) shouldBe DataType.pointer(BaseDataType.UWORD)
|
||||
DataType.arrayFor(BaseDataType.UWORD, true).typeForUntypedAddressOf(false, memsizer) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||
DataType.arrayFor(BaseDataType.UWORD, false).typeForUntypedAddressOf(true, memsizer) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||
DataType.arrayFor(BaseDataType.UWORD, true).typeForUntypedAddressOf(true, memsizer) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||
DataType.arrayFor(BaseDataType.FLOAT).typeForUntypedAddressOf(false, memsizer) shouldBe DataType.pointer(BaseDataType.FLOAT)
|
||||
DataType.arrayFor(BaseDataType.FLOAT).typeForUntypedAddressOf(true, memsizer) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||
DataType.arrayFor(BaseDataType.UWORD).typeForUntypedAddressOf(false, memsizer) shouldBe DataType.pointer(BaseDataType.UWORD)
|
||||
DataType.splitWordArrayFor(BaseDataType.UWORD).typeForUntypedAddressOf(false, memsizer) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||
DataType.arrayFor(BaseDataType.UWORD).typeForUntypedAddressOf(true, memsizer) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||
DataType.splitWordArrayFor(BaseDataType.UWORD).typeForUntypedAddressOf(true, memsizer) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||
|
||||
DataType.pointer(Struct("struct")).typeForUntypedAddressOf(false, memsizer) shouldBe DataType.UWORD
|
||||
DataType.pointerFromAntlr(listOf("struct")).typeForUntypedAddressOf(false, memsizer) shouldBe DataType.UWORD
|
||||
|
||||
@@ -7,18 +7,18 @@ import prog8.ast.Module
|
||||
import prog8.ast.Program
|
||||
import prog8.code.PROG8_CONTAINER_MODULES
|
||||
import prog8.code.source.SourceCode
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8.parser.ParseError
|
||||
import prog8.parser.Prog8Parser.parseModule
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.helpers.DummyStringEncoder
|
||||
|
||||
|
||||
class TestAstToSourceText: FunSpec({
|
||||
|
||||
// Helper function to generate Prog8 source from AST
|
||||
fun generateP8(module: Module): String {
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("test", DummyFunctions, target)
|
||||
.addModule(module)
|
||||
|
||||
var generatedText = ""
|
||||
|
||||
@@ -14,10 +14,9 @@ import prog8.ast.statements.Subroutine
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.source.SourceCode
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8.parser.Prog8Parser
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.helpers.DummyStringEncoder
|
||||
|
||||
|
||||
class TestIdentifierRef: FunSpec({
|
||||
@@ -55,7 +54,8 @@ class TestIdentifierRef: FunSpec({
|
||||
}
|
||||
} """)
|
||||
val module = Prog8Parser.parseModule(src)
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("test", DummyFunctions, target)
|
||||
program.addModule(module)
|
||||
val mstmts = (module.statements.single() as Block).statements
|
||||
val stmts = mstmts.filterIsInstance<Subroutine>().single().statements
|
||||
|
||||
@@ -677,9 +677,10 @@ class TestProg8Parser: FunSpec( {
|
||||
val char3 = CharLiteral.create('_', Encoding.ISO, Position.DUMMY)
|
||||
val char4 = CharLiteral.create('_', Encoding.DEFAULT, Position.DUMMY)
|
||||
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, AsciiStringEncoder)
|
||||
char1.constValue(program)?.number?.toInt() shouldBe 65
|
||||
char2.constValue(program)?.number?.toInt() shouldBe 122
|
||||
val target = VMTarget()
|
||||
val program = Program("test", DummyFunctions, target)
|
||||
char1.constValue(program)?.number?.toInt() shouldBe 193
|
||||
char2.constValue(program)?.number?.toInt() shouldBe 26
|
||||
char3.constValue(program)?.number?.toInt() shouldBe 95
|
||||
char4.constValue(program) shouldBe null
|
||||
}
|
||||
@@ -810,7 +811,8 @@ class TestProg8Parser: FunSpec( {
|
||||
}
|
||||
""")
|
||||
val module = parseModule(src)
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("test", DummyFunctions, target)
|
||||
program.addModule(module)
|
||||
val bb2 = (module.statements.single() as Block).statements[2] as VarDecl
|
||||
val expr = bb2.value as BinaryExpression
|
||||
@@ -833,7 +835,8 @@ class TestProg8Parser: FunSpec( {
|
||||
}
|
||||
""")
|
||||
val module = parseModule(src)
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("test", DummyFunctions, target)
|
||||
program.addModule(module)
|
||||
val stmts = (module.statements.single() as Block).statements
|
||||
stmts.size shouldBe 6
|
||||
@@ -860,7 +863,8 @@ class TestProg8Parser: FunSpec( {
|
||||
ubyte ub = (cos8(r)/2 + 100) as ubyte
|
||||
}""")
|
||||
val module = parseModule(src)
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("test", DummyFunctions, target)
|
||||
program.addModule(module)
|
||||
val stmts = (module.statements.single() as Block).statements
|
||||
stmts.size shouldBe 2
|
||||
@@ -891,7 +895,8 @@ class TestProg8Parser: FunSpec( {
|
||||
}""")
|
||||
|
||||
val module = parseModule(src)
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("test", DummyFunctions, target)
|
||||
program.addModule(module)
|
||||
val stmts = program.entrypoint.statements
|
||||
val expectedResults = listOf(
|
||||
|
||||
@@ -19,9 +19,8 @@ import prog8.code.ast.PtBlock
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.source.SourceCode
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.helpers.DummyStringEncoder
|
||||
import prog8tests.helpers.compileText
|
||||
|
||||
class TestProgram: FunSpec({
|
||||
@@ -30,7 +29,8 @@ class TestProgram: FunSpec({
|
||||
|
||||
context("Constructor") {
|
||||
test("withNameBuiltinsAndMemsizer") {
|
||||
val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("foo", DummyFunctions, target)
|
||||
program.modules.size shouldBe PROG8_CONTAINER_MODULES.size
|
||||
program.modules[0].name shouldBe INTERNED_STRINGS_MODULENAME
|
||||
program.modules[0].program shouldBeSameInstanceAs program
|
||||
@@ -40,7 +40,8 @@ class TestProgram: FunSpec({
|
||||
|
||||
context("AddModule") {
|
||||
test("withEmptyModule") {
|
||||
val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("foo", DummyFunctions, target)
|
||||
val m1 = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("bar"))
|
||||
|
||||
val retVal = program.addModule(m1)
|
||||
@@ -66,7 +67,8 @@ class TestProgram: FunSpec({
|
||||
|
||||
context("MoveModuleToFront") {
|
||||
test("withInternedStringsModule") {
|
||||
val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("foo", DummyFunctions, target)
|
||||
val m = program.modules[0]
|
||||
m.name shouldBe INTERNED_STRINGS_MODULENAME
|
||||
|
||||
@@ -76,14 +78,16 @@ class TestProgram: FunSpec({
|
||||
}
|
||||
|
||||
test("withForeignModule") {
|
||||
val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("foo", DummyFunctions, target)
|
||||
val m = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("bar"))
|
||||
|
||||
shouldThrow<IllegalArgumentException> { program.moveModuleToFront(m) }
|
||||
}
|
||||
|
||||
test("withFirstOfPreviouslyAddedModules") {
|
||||
val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("foo", DummyFunctions, target)
|
||||
val m1 = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("bar"))
|
||||
val m2 = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("qmbl"))
|
||||
program.addModule(m1)
|
||||
@@ -95,7 +99,8 @@ class TestProgram: FunSpec({
|
||||
}
|
||||
|
||||
test("withSecondOfPreviouslyAddedModules") {
|
||||
val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("foo", DummyFunctions, target)
|
||||
val m1 = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("bar"))
|
||||
val m2 = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated("qmbl"))
|
||||
program.addModule(m1)
|
||||
@@ -109,7 +114,8 @@ class TestProgram: FunSpec({
|
||||
|
||||
context("Properties") {
|
||||
test("modules") {
|
||||
val program = Program("foo", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
val target = VMTarget()
|
||||
val program = Program("foo", DummyFunctions, target)
|
||||
|
||||
val ms1 = program.modules
|
||||
val ms2 = program.modules
|
||||
|
||||
@@ -1070,13 +1070,12 @@ main {
|
||||
DataType.forDt(BaseDataType.STR).isString shouldBe true
|
||||
DataType.forDt(BaseDataType.FLOAT).isFloat shouldBe true
|
||||
|
||||
DataType.arrayFor(BaseDataType.UBYTE, true).isUnsignedByteArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.LONG).isLongArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.FLOAT).isFloatArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD).isUnsignedWordArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD).isArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD).isSplitWordArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD, false).isSplitWordArray shouldBe false
|
||||
DataType.splitWordArrayFor(BaseDataType.UWORD).isSplitWordArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD).isSplitWordArray shouldBe false
|
||||
|
||||
shouldThrow<NoSuchElementException> {
|
||||
DataType.forDt(BaseDataType.ARRAY)
|
||||
@@ -1112,7 +1111,7 @@ main {
|
||||
(st1[1] as VarDecl).name shouldBe "names"
|
||||
val array1 = (st1[1] as VarDecl).value as ArrayLiteral
|
||||
array1.type.isArray shouldBe true
|
||||
array1.type.getOrUndef() shouldBe DataType.arrayFor(BaseDataType.UWORD, true)
|
||||
array1.type.getOrUndef() shouldBe DataType.splitWordArrayFor(BaseDataType.UWORD)
|
||||
|
||||
val ast2 = result.codegenAst!!
|
||||
val st2 = ast2.entrypoint()!!.children
|
||||
@@ -1120,7 +1119,7 @@ main {
|
||||
(st2[1] as PtVariable).name shouldBe "p8v_variable"
|
||||
(st2[2] as PtVariable).name shouldBe "p8v_names"
|
||||
val array2 = (st2[2] as PtVariable).value as PtArray
|
||||
array2.type shouldBe DataType.arrayFor(BaseDataType.UWORD, true)
|
||||
array2.type shouldBe DataType.splitWordArrayFor(BaseDataType.UWORD)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,10 +21,13 @@ import prog8.code.target.VMTarget
|
||||
import prog8.codegen.cpu6502.AsmGen6502Internal
|
||||
import prog8.compiler.astprocessing.AstChecker
|
||||
import prog8.compiler.astprocessing.SimplifiedAstMaker
|
||||
import prog8tests.helpers.*
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
import prog8tests.helpers.compileText
|
||||
|
||||
class TestAsmGenSymbols: StringSpec({
|
||||
val outputDir = tempdir().toPath()
|
||||
val target = VMTarget()
|
||||
|
||||
fun createTestProgram(): Program {
|
||||
/*
|
||||
@@ -78,7 +81,7 @@ class TestAsmGenSymbols: StringSpec({
|
||||
val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY)
|
||||
|
||||
val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test"))
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder).addModule(module)
|
||||
val program = Program("test", DummyFunctions, target).addModule(module)
|
||||
|
||||
return program
|
||||
}
|
||||
@@ -171,8 +174,8 @@ main {
|
||||
asmgen.asmSymbolName(listOf("prog8_lib","P8ZP_SCRATCH_W2")) shouldBe "P8ZP_SCRATCH_W2"
|
||||
val id1 = PtIdentifier("prog8_lib.P8ZP_SCRATCH_REG", DataType.UBYTE, Position.DUMMY)
|
||||
val id2 = PtIdentifier("prog8_lib.P8ZP_SCRATCH_W2", DataType.UWORD, Position.DUMMY)
|
||||
id1.parent = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
id2.parent = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
id1.parent = PtProgram("test", VMTarget())
|
||||
id2.parent = PtProgram("test", VMTarget())
|
||||
asmgen.asmSymbolName(id1) shouldBe "P8ZP_SCRATCH_REG"
|
||||
asmgen.asmSymbolName(id2) shouldBe "P8ZP_SCRATCH_W2"
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ library {
|
||||
main.name shouldBe "p8b_main"
|
||||
val jumptable = main.children[0] as PtVariable
|
||||
jumptable.name shouldBe "p8v_jumptable"
|
||||
jumptable.type shouldBe DataType.arrayFor(BaseDataType.UWORD, false)
|
||||
jumptable.type shouldBe DataType.arrayFor(BaseDataType.UWORD)
|
||||
jumptable.arraySize shouldBe 4u
|
||||
val bin = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".bin").readBytes().map { it.toUByte() }
|
||||
|
||||
@@ -144,7 +144,7 @@ library {
|
||||
main.name shouldBe "p8b_main"
|
||||
val jumptable = main.children[0] as PtVariable
|
||||
jumptable.name shouldBe "p8v_jumptable"
|
||||
jumptable.type shouldBe DataType.arrayFor(BaseDataType.UWORD, false)
|
||||
jumptable.type shouldBe DataType.arrayFor(BaseDataType.UWORD)
|
||||
jumptable.arraySize shouldBe 4u
|
||||
val asm = result.compilationOptions.outputDir.resolve(result.compilerAst.name + ".asm").readText()
|
||||
println(asm)
|
||||
@@ -187,4 +187,4 @@ library {
|
||||
// check func2
|
||||
bin[offset(func2Addr)] shouldBe 0xCeu // DEC abs
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -67,7 +67,7 @@ main {
|
||||
val text="""
|
||||
main {
|
||||
sub start() {
|
||||
uword[3] seed
|
||||
uword[3] @nosplit seed
|
||||
cx16.r0 = seed[0] + seed[1] + seed[2]
|
||||
}
|
||||
}"""
|
||||
|
||||
@@ -434,9 +434,9 @@ open class Module(final override val statements: MutableList<Statement>,
|
||||
val textEncoding: Encoding by lazy {
|
||||
val encoding = statements.singleOrNull { it is Directive && it.directive == "%encoding" } as? Directive
|
||||
if(encoding!=null)
|
||||
Encoding.entries.firstOrNull { it.prefix==encoding.args[0].string } ?: program.encoding.defaultEncoding // invalid encoding will be noticed by ast checker error message
|
||||
Encoding.entries.firstOrNull { it.prefix==encoding.args[0].string } ?: program.target.defaultEncoding // invalid encoding will be noticed by ast checker error message
|
||||
else
|
||||
program.encoding.defaultEncoding
|
||||
program.target.defaultEncoding
|
||||
}
|
||||
|
||||
val isLibrary get() = source.isFromLibrary
|
||||
|
||||
@@ -14,8 +14,7 @@ import prog8.code.source.SourceCode
|
||||
|
||||
class Program(val name: String,
|
||||
val builtinFunctions: IBuiltinFunctions,
|
||||
val memsizer: IMemSizer,
|
||||
val encoding: IStringEncoding
|
||||
val target: ICompilationTarget
|
||||
) {
|
||||
private val _modules = mutableListOf<Module>()
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.core.*
|
||||
import prog8.code.source.SourceCode
|
||||
|
||||
import prog8.parser.Prog8ANTLRParser.*
|
||||
import prog8.parser.Prog8ANTLRVisitor
|
||||
import kotlin.io.path.Path
|
||||
@@ -218,7 +219,7 @@ class Antlr2KotlinVisitor(val source: SourceCode): AbstractParseTreeVisitor<Node
|
||||
else if(baseDt.isStructInstance)
|
||||
throw SyntaxError("array of structures not allowed (use array of pointers)", ctx.toPosition())
|
||||
else
|
||||
DataType.arrayFor(baseDt.base, split!=SplitWish.NOSPLIT)
|
||||
DataType.arrayFor(baseDt.base)
|
||||
}
|
||||
|
||||
return VarDecl.builder(dt, ctx.toPosition())
|
||||
|
||||
@@ -669,7 +669,7 @@ data class AddressOf(var identifier: IdentifierReference?, var arrayIndex: Array
|
||||
if (index != null) {
|
||||
address += when {
|
||||
target.datatype.isInteger -> index
|
||||
target.datatype.isPointer || target.datatype.isArray -> index * targetVar.datatype.size(program.memsizer)
|
||||
target.datatype.isPointer || target.datatype.isArray -> index * targetVar.datatype.size(program.target)
|
||||
else -> throw FatalAstException("need array or ptr")
|
||||
}
|
||||
} else
|
||||
@@ -691,16 +691,16 @@ data class AddressOf(var identifier: IdentifierReference?, var arrayIndex: Array
|
||||
override fun referencesIdentifier(nameInSource: List<String>) = identifier?.nameInSource==nameInSource || arrayIndex?.referencesIdentifier(nameInSource)==true || dereference?.referencesIdentifier(nameInSource)==true
|
||||
override fun inferType(program: Program): InferredTypes.InferredType {
|
||||
if(!typed) {
|
||||
val untypedPointerType = if(program.memsizer.memorySize(BaseDataType.POINTER)>2) BaseDataType.LONG else BaseDataType.UWORD
|
||||
val untypedPointerType = if(program.target.memorySize(BaseDataType.POINTER)>2) BaseDataType.LONG else BaseDataType.UWORD
|
||||
return InferredTypes.knownFor(untypedPointerType)
|
||||
}
|
||||
if(identifier!=null) {
|
||||
val type = identifier!!.inferType(program).getOrUndef()
|
||||
val addrofDt = type.typeForUntypedAddressOf(msb, program.memsizer)
|
||||
val addrofDt = type.typeForUntypedAddressOf(msb, program.target)
|
||||
return if(addrofDt.isUndefined) InferredTypes.unknown() else InferredTypes.knownFor(addrofDt)
|
||||
} else if(dereference!=null) {
|
||||
val type = dereference!!.inferType(program).getOrUndef()
|
||||
val addrofDt = type.typeForUntypedAddressOf(msb, program.memsizer)
|
||||
val addrofDt = type.typeForUntypedAddressOf(msb, program.target)
|
||||
return if(addrofDt.isUndefined) InferredTypes.unknown() else InferredTypes.knownFor(addrofDt)
|
||||
} else
|
||||
throw FatalAstException("invalid addressof")
|
||||
@@ -1149,7 +1149,7 @@ class CharLiteral private constructor(val value: Char,
|
||||
override fun constValue(program: Program): NumericLiteral? {
|
||||
if(encoding== Encoding.DEFAULT) // will be determined at a later stage, hopefully
|
||||
return null
|
||||
val bytevalue = program.encoding.encodeString(value.toString(), encoding).single()
|
||||
val bytevalue = program.target.encodeString(value.toString(), encoding).single()
|
||||
return NumericLiteral(BaseDataType.UBYTE, bytevalue.toDouble(), position)
|
||||
}
|
||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||
@@ -1794,7 +1794,7 @@ class ContainmentCheck(var element: Expression,
|
||||
val stringval = iterable as StringLiteral
|
||||
if(stringval.encoding== Encoding.DEFAULT) // will be set at a later stage, hopefully
|
||||
return null
|
||||
val exists = program.encoding.encodeString(stringval.value, stringval.encoding).contains(elementConst.number.toInt().toUByte() )
|
||||
val exists = program.target.encodeString(stringval.value, stringval.encoding).contains(elementConst.number.toInt().toUByte() )
|
||||
return NumericLiteral.fromBoolean(exists, position)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,21 +107,6 @@ object InferredTypes {
|
||||
if(instance!=null)
|
||||
return instance
|
||||
else
|
||||
return when {
|
||||
type.isPointerArray -> InferredType.known(type)
|
||||
type.isSplitWordArray -> {
|
||||
when (type.sub) {
|
||||
BaseDataType.UWORD -> InferredType.known(DataType.arrayFor(BaseDataType.UWORD))
|
||||
BaseDataType.WORD -> InferredType.known(DataType.arrayFor(BaseDataType.WORD))
|
||||
BaseDataType.STR -> InferredType.known(DataType.arrayFor(BaseDataType.STR))
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
|
||||
type.isArray -> InferredType.known(type)
|
||||
type.isPointer -> InferredType.known(type)
|
||||
type.isStructInstance -> InferredType.known(type)
|
||||
else -> throw IllegalArgumentException("invalid type $type")
|
||||
}
|
||||
return InferredType.known(type)
|
||||
}
|
||||
}
|
||||
@@ -389,14 +389,14 @@ class VarDecl(
|
||||
.build()
|
||||
}
|
||||
|
||||
fun createAuto(array: ArrayLiteral): VarDecl {
|
||||
fun createAuto(array: ArrayLiteral, target: ICompilationTarget): VarDecl {
|
||||
val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}"
|
||||
var arrayDt = array.type.getOrElse { throw FatalAstException("unknown dt") }
|
||||
if(arrayDt.isSplitWordArray) {
|
||||
// autovars for array literals are NEVER stored as a split word array!
|
||||
when(arrayDt.sub) {
|
||||
BaseDataType.WORD -> arrayDt = DataType.arrayFor(BaseDataType.WORD, false)
|
||||
BaseDataType.UWORD -> arrayDt = DataType.arrayFor(BaseDataType.UWORD, false)
|
||||
BaseDataType.WORD -> arrayDt = DataType.arrayFor(BaseDataType.WORD)
|
||||
BaseDataType.UWORD -> arrayDt = DataType.arrayFor(BaseDataType.UWORD)
|
||||
else -> { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,8 @@ class IRFileReader {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var options: CompilationOptions
|
||||
|
||||
private fun parseProgram(reader: XMLEventReader): IRProgram {
|
||||
require(reader.nextEvent().isStartDocument)
|
||||
@@ -64,7 +66,7 @@ class IRFileReader {
|
||||
require(start.name.localPart=="PROGRAM") { "missing PROGRAM" }
|
||||
val programName = start.attributes.asSequence().single { it.name.localPart == "NAME" }.value
|
||||
val compilerVersion = start.attributes.asSequence().single { it.name.localPart == "COMPILERVERSION" }.value
|
||||
val options = parseOptions(reader, compilerVersion)
|
||||
options = parseOptions(reader, compilerVersion)
|
||||
val asmsymbols = parseAsmSymbols(reader)
|
||||
|
||||
skipText(reader)
|
||||
@@ -612,13 +614,13 @@ class IRFileReader {
|
||||
}
|
||||
}
|
||||
return when(type) {
|
||||
"bool" -> DataType.arrayFor(BaseDataType.BOOL, false)
|
||||
"byte" -> DataType.arrayFor(BaseDataType.BYTE, false)
|
||||
"ubyte", "str" -> DataType.arrayFor(BaseDataType.UBYTE, false)
|
||||
"word" -> DataType.arrayFor(BaseDataType.WORD, false)
|
||||
"uword" -> DataType.arrayFor(BaseDataType.UWORD, false)
|
||||
"float" -> DataType.arrayFor(BaseDataType.FLOAT, false)
|
||||
"long" -> DataType.arrayFor(BaseDataType.LONG, false)
|
||||
"bool" -> DataType.arrayFor(BaseDataType.BOOL)
|
||||
"byte" -> DataType.arrayFor(BaseDataType.BYTE)
|
||||
"ubyte", "str" -> DataType.arrayFor(BaseDataType.UBYTE)
|
||||
"word" -> DataType.arrayFor(BaseDataType.WORD)
|
||||
"uword" -> DataType.arrayFor(BaseDataType.UWORD)
|
||||
"float" -> DataType.arrayFor(BaseDataType.FLOAT)
|
||||
"long" -> DataType.arrayFor(BaseDataType.LONG)
|
||||
else -> {
|
||||
throw IRParseException("invalid dt $type")
|
||||
}
|
||||
|
||||
@@ -132,15 +132,14 @@ sealed class PtNamedNode(initialName: String, position: Position): PtNode(positi
|
||||
|
||||
class PtProgram(
|
||||
val name: String,
|
||||
val memsizer: IMemSizer,
|
||||
val encoding: IStringEncoding
|
||||
val target: ICompilationTarget
|
||||
) : PtNode(Position.DUMMY) {
|
||||
val memsizer: IMemSizer get() = target
|
||||
val encoding: IStringEncoding get() = target
|
||||
|
||||
// Root node is never transformed - return self
|
||||
override fun copy(): PtNode = this
|
||||
|
||||
// fun allModuleDirectives(): Sequence<PtDirective> =
|
||||
// children.asSequence().flatMap { it.children }.filterIsInstance<PtDirective>().distinct()
|
||||
|
||||
fun allBlocks(): Sequence<PtBlock> =
|
||||
children.asSequence().filterIsInstance<PtBlock>()
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@ import prog8.code.core.DataType
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.optimize.ComparisonOptimizers
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.helpers.DummyStringEncoder
|
||||
|
||||
|
||||
/**
|
||||
* Tests for ComparisonOptimizers, particularly the optimizeComparisonIdentities function.
|
||||
@@ -21,7 +20,7 @@ class TestComparisonOptimizers: FunSpec({
|
||||
|
||||
// Helper to create a simple program with a binary expression in a sub
|
||||
fun createProgramWithComparison(operator: String, leftType: DataType): PtProgram {
|
||||
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val program = PtProgram("test", VMTarget())
|
||||
val block = PtBlock("main", false, prog8.code.source.SourceCode.Generated("main"), PtBlock.Options(), Position.DUMMY)
|
||||
program.add(block)
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ import prog8.code.core.DataType
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.core.ZeropageWish
|
||||
import prog8.code.source.SourceCode
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.helpers.DummyStringEncoder
|
||||
import prog8.code.target.VMTarget
|
||||
|
||||
/**
|
||||
* Tests for SymbolTable construction and structural integrity.
|
||||
@@ -32,14 +31,14 @@ class TestSymbolTableConstruction: FunSpec({
|
||||
// ============================================================================
|
||||
|
||||
fun makeSimpleSymbolTable(): SymbolTable {
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astProgram = PtProgram("test", VMTarget())
|
||||
val astBlock = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
astProgram.add(astBlock)
|
||||
return SymbolTable(astProgram)
|
||||
}
|
||||
|
||||
fun makeSymbolTableWithDuplicates(): Pair<SymbolTable, StStaticVariable> {
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astProgram = PtProgram("test", VMTarget())
|
||||
val astBlock = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
astProgram.add(astBlock)
|
||||
val st = SymbolTable(astProgram)
|
||||
@@ -59,7 +58,7 @@ class TestSymbolTableConstruction: FunSpec({
|
||||
// ============================================================================
|
||||
|
||||
test("empty symboltable creation") {
|
||||
val astNode = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astNode = PtProgram("test", VMTarget())
|
||||
val st = SymbolTable(astNode)
|
||||
st.name shouldBe "test"
|
||||
st.type shouldBe StNodeType.GLOBAL
|
||||
@@ -75,7 +74,7 @@ class TestSymbolTableConstruction: FunSpec({
|
||||
}
|
||||
|
||||
test("symboltable with multiple modules") {
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astProgram = PtProgram("test", VMTarget())
|
||||
val astBlock1 = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
val astBlock2 = PtBlock("block2", false, SourceCode.Generated("block2"), PtBlock.Options(), Position.DUMMY)
|
||||
astProgram.add(astBlock1)
|
||||
@@ -100,7 +99,7 @@ class TestSymbolTableConstruction: FunSpec({
|
||||
}
|
||||
|
||||
test("duplicate struct instance insertion is handled") {
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astProgram = PtProgram("test", VMTarget())
|
||||
val astBlock = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
astProgram.add(astBlock)
|
||||
val st = SymbolTable(astProgram)
|
||||
@@ -119,7 +118,7 @@ class TestSymbolTableConstruction: FunSpec({
|
||||
}
|
||||
|
||||
test("duplicate memory slab insertion is handled") {
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astProgram = PtProgram("test", VMTarget())
|
||||
val astBlock = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
astProgram.add(astBlock)
|
||||
val st = SymbolTable(astProgram)
|
||||
@@ -138,7 +137,7 @@ class TestSymbolTableConstruction: FunSpec({
|
||||
}
|
||||
|
||||
test("duplicate label insertion is handled") {
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astProgram = PtProgram("test", VMTarget())
|
||||
val astBlock = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
astProgram.add(astBlock)
|
||||
val st = SymbolTable(astProgram)
|
||||
@@ -218,7 +217,7 @@ class TestSymbolTableConstruction: FunSpec({
|
||||
// ================================================================================
|
||||
|
||||
private fun makeStWithVariables(): SymbolTable {
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astProgram = PtProgram("test", VMTarget())
|
||||
val astBlock = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
astProgram.add(astBlock)
|
||||
val st = SymbolTable(astProgram)
|
||||
@@ -235,7 +234,7 @@ private fun makeStWithVariables(): SymbolTable {
|
||||
}
|
||||
|
||||
private fun makeStWithMemVars(): SymbolTable {
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astProgram = PtProgram("test", VMTarget())
|
||||
val astBlock = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
astProgram.add(astBlock)
|
||||
val st = SymbolTable(astProgram)
|
||||
@@ -250,7 +249,7 @@ private fun makeStWithMemVars(): SymbolTable {
|
||||
}
|
||||
|
||||
private fun makeStWithSlabs(): SymbolTable {
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astProgram = PtProgram("test", VMTarget())
|
||||
val astBlock = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
astProgram.add(astBlock)
|
||||
val st = SymbolTable(astProgram)
|
||||
@@ -265,7 +264,7 @@ private fun makeStWithSlabs(): SymbolTable {
|
||||
}
|
||||
|
||||
private fun makeStWithStructInstances(): SymbolTable {
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astProgram = PtProgram("test", VMTarget())
|
||||
val astBlock = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
astProgram.add(astBlock)
|
||||
val st = SymbolTable(astProgram)
|
||||
@@ -280,7 +279,7 @@ private fun makeStWithStructInstances(): SymbolTable {
|
||||
}
|
||||
|
||||
private fun makeStWithStructs(): SymbolTable {
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astProgram = PtProgram("test", VMTarget())
|
||||
val astBlock = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
astProgram.add(astBlock)
|
||||
val st = SymbolTable(astProgram)
|
||||
|
||||
Reference in new issue
Block a user