mirror of
https://github.com/irmen/prog8.git
synced 2025-11-02 13:16:07 +00:00
simplify
This commit is contained in:
@@ -84,7 +84,11 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
|
|||||||
}
|
}
|
||||||
base==BaseDataType.STR -> require(sub==BaseDataType.UBYTE) { "string subtype should be ubyte" }
|
base==BaseDataType.STR -> require(sub==BaseDataType.UBYTE) { "string subtype should be ubyte" }
|
||||||
base!=BaseDataType.POINTER -> require(sub == null) { "only string, array and pointer base types can have a subtype"}
|
base!=BaseDataType.POINTER -> require(sub == null) { "only string, array and pointer base types can have a subtype"}
|
||||||
else -> require(sub == null || (subType == null && subTypeFromAntlr == null)) { "sub and subtype can't both be set" }
|
else -> {
|
||||||
|
require(sub == null || (subType == null && subTypeFromAntlr == null)) {
|
||||||
|
"sub and subtype can't both be set"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,15 +148,21 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun arrayOfPointersTo(sub: BaseDataType?, subType: ISubType?): DataType =
|
fun arrayOfPointersTo(sub: BaseDataType): DataType = DataType(BaseDataType.ARRAY_POINTER, sub, null)
|
||||||
DataType(BaseDataType.ARRAY_POINTER, sub, subType)
|
fun arrayOfPointersTo(structType: ISubType?): DataType = DataType(BaseDataType.ARRAY_POINTER, null, structType)
|
||||||
fun arrayOfPointersFromAntlrTo(sub: BaseDataType?, identifier: List<String>?): DataType =
|
fun arrayOfPointersFromAntlrTo(sub: BaseDataType?, identifier: List<String>?): DataType =
|
||||||
DataType(BaseDataType.ARRAY_POINTER, sub, null, identifier)
|
DataType(BaseDataType.ARRAY_POINTER, sub, null, identifier)
|
||||||
|
|
||||||
fun pointer(base: BaseDataType): DataType = DataType(BaseDataType.POINTER, base, null)
|
fun pointer(base: BaseDataType): DataType = DataType(BaseDataType.POINTER, base, null)
|
||||||
fun pointerToType(type: ISubType): DataType = DataType(BaseDataType.POINTER, null, type)
|
fun pointer(dt: DataType): DataType {
|
||||||
fun structInstance(type: ISubType?): DataType = DataType(BaseDataType.STRUCT_INSTANCE, sub=null, type)
|
if(dt.isBasic)
|
||||||
|
return DataType(BaseDataType.POINTER, dt.base, null)
|
||||||
|
else
|
||||||
|
return DataType(BaseDataType.POINTER, null, dt.subType, dt.subTypeFromAntlr)
|
||||||
|
}
|
||||||
|
fun pointer(structType: ISubType): DataType = DataType(BaseDataType.POINTER, null, structType, null)
|
||||||
fun pointerFromAntlr(identifier: List<String>): DataType = DataType(BaseDataType.POINTER, null, null, identifier)
|
fun pointerFromAntlr(identifier: List<String>): DataType = DataType(BaseDataType.POINTER, null, null, identifier)
|
||||||
|
fun structInstance(type: ISubType?): DataType = DataType(BaseDataType.STRUCT_INSTANCE, sub=null, type)
|
||||||
fun structInstanceFromAntlr(struct: List<String>): DataType = DataType(BaseDataType.STRUCT_INSTANCE, null, null, subTypeFromAntlr = struct)
|
fun structInstanceFromAntlr(struct: List<String>): DataType = DataType(BaseDataType.STRUCT_INSTANCE, null, null, subTypeFromAntlr = struct)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,10 +194,10 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
|
|||||||
return pointer(BaseDataType.UBYTE)
|
return pointer(BaseDataType.UBYTE)
|
||||||
val elementDt = elementType()
|
val elementDt = elementType()
|
||||||
require(elementDt.isBasic)
|
require(elementDt.isBasic)
|
||||||
return pointer(elementDt.base)
|
return pointer(elementDt)
|
||||||
}
|
}
|
||||||
if (subType != null)
|
if (subType != null)
|
||||||
return pointerToType(subType!!)
|
return pointer(this)
|
||||||
return UWORD
|
return UWORD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,25 +98,28 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(idxderef: PtPointerIndexedDeref): ExpressionCodeResult {
|
private fun translate(idxderef: PtPointerIndexedDeref): ExpressionCodeResult {
|
||||||
val idx = idxderef.indexer
|
|
||||||
if (idxderef.type.isStructInstance)
|
if (idxderef.type.isStructInstance)
|
||||||
throw AssemblyError("cannot translate POINTER[x] resulting in a struct instance (only when it results in a basic type); this is likely part of a larger expression POINTER[x].field and that has to be translated earlier as a whole")
|
throw AssemblyError("cannot translate POINTER[x] resulting in a struct instance (only when it results in a basic type); this is likely part of a larger expression POINTER[x].field and that has to be translated earlier as a whole")
|
||||||
|
|
||||||
val eltSize = codeGen.program.memsizer.memorySize(idxderef.type, null)
|
val eltSize = codeGen.program.memsizer.memorySize(idxderef.type, null)
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val pointerTr = translateExpression(idx.variable)
|
if(!idxderef.variable.type.isPointer) {
|
||||||
result += pointerTr.chunks
|
TODO("expression: indexing non-pointer field ${idxderef.variable}")
|
||||||
val pointerReg = pointerTr.resultReg
|
}
|
||||||
val constIndex = idx.index.asConstInteger()
|
|
||||||
|
TODO("evaluate address of pointer dereference ${idxderef.position}")
|
||||||
|
|
||||||
|
val pointerReg = -1 // pointerTr.resultReg
|
||||||
|
val constIndex = idxderef.index.asConstInteger()
|
||||||
if(constIndex!=null) {
|
if(constIndex!=null) {
|
||||||
val offset = constIndex * eltSize
|
val offset = constIndex * eltSize
|
||||||
addInstr(result, IRInstruction(Opcode.ADD, IRDataType.WORD, reg1 = pointerReg, immediate = offset), null)
|
addInstr(result, IRInstruction(Opcode.ADD, IRDataType.WORD, reg1 = pointerReg, immediate = offset), null)
|
||||||
} else {
|
} else {
|
||||||
val indexTr = translateExpression(idx.index)
|
val indexTr = translateExpression(idxderef.index)
|
||||||
result += indexTr.chunks
|
result += indexTr.chunks
|
||||||
result += IRCodeChunk(null, null).also {
|
result += IRCodeChunk(null, null).also {
|
||||||
val indexReg: Int
|
val indexReg: Int
|
||||||
if (idx.index.type.isByte) {
|
if (idxderef.index.type.isByte) {
|
||||||
// extend array index to word
|
// extend array index to word
|
||||||
indexReg = codeGen.registers.next(IRDataType.WORD)
|
indexReg = codeGen.registers.next(IRDataType.WORD)
|
||||||
it += IRInstruction(Opcode.EXT, IRDataType.BYTE, indexReg, indexTr.resultReg)
|
it += IRInstruction(Opcode.EXT, IRDataType.BYTE, indexReg, indexTr.resultReg)
|
||||||
|
|||||||
@@ -108,21 +108,12 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
|||||||
val type = idxderef.inferType(program).getOrElse {
|
val type = idxderef.inferType(program).getOrElse {
|
||||||
throw FatalAstException("unknown dt")
|
throw FatalAstException("unknown dt")
|
||||||
}
|
}
|
||||||
require(type.isPointer || type.isUnsignedWord)
|
val derefType = if(type.isPointer) DataType.forDt(type.sub!!) else type
|
||||||
if(type.isUnsignedWord) {
|
val deref = PtPointerIndexedDeref(derefType, idxderef.position)
|
||||||
if(idxderef.parent is AssignTarget)
|
val identifier = PtIdentifier(idxderef.indexed.arrayvar.nameInSource.joinToString("."), DataType.pointer(derefType), idxderef.indexed.arrayvar.position)
|
||||||
TODO("as assignment target: indexing uword field $idxderef") // TODO hmm, wasn't there code elsewhere for this already?
|
deref.add(identifier)
|
||||||
else
|
deref.add(transformExpression(idxderef.indexed.indexer.indexExpr))
|
||||||
TODO("as value: indexing uword field $idxderef") // TODO hmm, wasn't there code elsewhere for this already?
|
return deref
|
||||||
} else {
|
|
||||||
val deref = PtPointerIndexedDeref(DataType.forDt(type.sub!!), idxderef.position)
|
|
||||||
val indexer = PtArrayIndexer(DataType.forDt(type.sub!!), idxderef.position)
|
|
||||||
val identifier = PtIdentifier(idxderef.indexed.arrayvar.nameInSource.joinToString("."), type, idxderef.indexed.arrayvar.position)
|
|
||||||
indexer.add(identifier)
|
|
||||||
indexer.add(transformExpression(idxderef.indexed.indexer.indexExpr))
|
|
||||||
deref.add(indexer)
|
|
||||||
return deref
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(deref: PtrDereference): PtPointerDeref {
|
private fun transform(deref: PtrDereference): PtPointerDeref {
|
||||||
@@ -411,8 +402,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
|||||||
val call =
|
val call =
|
||||||
if(targetStruct!=null) {
|
if(targetStruct!=null) {
|
||||||
// a call to a struct yields a pointer to a struct instance and means: allocate a statically initialized struct instance of that type
|
// a call to a struct yields a pointer to a struct instance and means: allocate a statically initialized struct instance of that type
|
||||||
val pointertype = DataType.pointerToType(targetStruct)
|
PtBuiltinFunctionCall("structalloc", false, true, DataType.pointer(targetStruct), srcCall.position)
|
||||||
PtBuiltinFunctionCall("structalloc", false, true, pointertype, srcCall.position)
|
|
||||||
} else {
|
} else {
|
||||||
// regular function call
|
// regular function call
|
||||||
val (target, _) = srcCall.target.targetNameAndType(program)
|
val (target, _) = srcCall.target.targetNameAndType(program)
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
|||||||
changeDataType = if(decl.datatype.isSplitWordArray) null else {
|
changeDataType = if(decl.datatype.isSplitWordArray) null else {
|
||||||
val eltDt = decl.datatype.elementType()
|
val eltDt = decl.datatype.elementType()
|
||||||
if(eltDt.isPointer)
|
if(eltDt.isPointer)
|
||||||
DataType.arrayOfPointersTo(eltDt.base, eltDt.subType)
|
TODO("convert array of pointers to split words array type")
|
||||||
else
|
else
|
||||||
DataType.arrayFor(eltDt.base)
|
DataType.arrayFor(eltDt.base)
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,7 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
|||||||
changeDataType = if(decl.datatype.isSplitWordArray) null else {
|
changeDataType = if(decl.datatype.isSplitWordArray) null else {
|
||||||
val eltDt = decl.datatype.elementType()
|
val eltDt = decl.datatype.elementType()
|
||||||
if(eltDt.isPointer)
|
if(eltDt.isPointer)
|
||||||
DataType.arrayOfPointersTo(eltDt.base, eltDt.subType)
|
TODO("convert array of pointers to split words array type")
|
||||||
else
|
else
|
||||||
DataType.arrayFor(eltDt.base)
|
DataType.arrayFor(eltDt.base)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ main {
|
|||||||
DataType.arrayFor(BaseDataType.UWORD, false).typeForAddressOf(true) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
DataType.arrayFor(BaseDataType.UWORD, false).typeForAddressOf(true) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||||
DataType.arrayFor(BaseDataType.UWORD, true).typeForAddressOf(true) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
DataType.arrayFor(BaseDataType.UWORD, true).typeForAddressOf(true) shouldBe DataType.pointer(BaseDataType.UBYTE)
|
||||||
|
|
||||||
DataType.pointerToType(Struct("struct")).typeForAddressOf(false) shouldBe DataType.UWORD
|
DataType.pointer(Struct("struct")).typeForAddressOf(false) shouldBe DataType.UWORD
|
||||||
DataType.pointerFromAntlr(listOf("struct")).typeForAddressOf(false) shouldBe DataType.UWORD
|
DataType.pointerFromAntlr(listOf("struct")).typeForAddressOf(false) shouldBe DataType.UWORD
|
||||||
|
|
||||||
DataType.pointer(BaseDataType.BOOL).typeForAddressOf(false) shouldBe DataType.UWORD
|
DataType.pointer(BaseDataType.BOOL).typeForAddressOf(false) shouldBe DataType.UWORD
|
||||||
|
|||||||
@@ -1093,7 +1093,10 @@ class ArrayLiteral(val type: InferredTypes.InferredType, // inferred because
|
|||||||
val unique = dts.toSet()
|
val unique = dts.toSet()
|
||||||
if(unique.size==1) {
|
if(unique.size==1) {
|
||||||
val dt = unique.single()
|
val dt = unique.single()
|
||||||
return InferredTypes.knownFor(DataType.arrayOfPointersTo(dt.sub, dt.subType))
|
return if(dt.subType!=null)
|
||||||
|
InferredTypes.knownFor(DataType.arrayOfPointersTo(dt.subType!!))
|
||||||
|
else
|
||||||
|
InferredTypes.knownFor(DataType.arrayOfPointersTo(dt.sub!!))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return when {
|
return when {
|
||||||
@@ -1474,7 +1477,7 @@ class FunctionCallExpression(override var target: IdentifierReference,
|
|||||||
}
|
}
|
||||||
is StructDecl -> {
|
is StructDecl -> {
|
||||||
// calling a struct is syntax for allocating a static instance, and returns a pointer to that (not the instance itself)
|
// calling a struct is syntax for allocating a static instance, and returns a pointer to that (not the instance itself)
|
||||||
return InferredTypes.knownFor(DataType.pointerToType(stmt))
|
return InferredTypes.knownFor(DataType.pointer(stmt))
|
||||||
}
|
}
|
||||||
else -> return InferredTypes.unknown()
|
else -> return InferredTypes.unknown()
|
||||||
}
|
}
|
||||||
@@ -1691,7 +1694,7 @@ class PtrDereference(val identifier: IdentifierReference, val chain: List<String
|
|||||||
struct = fieldDt.subType as StructDecl
|
struct = fieldDt.subType as StructDecl
|
||||||
}
|
}
|
||||||
if(field==null) {
|
if(field==null) {
|
||||||
return InferredTypes.knownFor(DataType.pointerToType(struct))
|
return InferredTypes.knownFor(DataType.pointer(struct))
|
||||||
}
|
}
|
||||||
val fieldDt = struct.getFieldType(field)
|
val fieldDt = struct.getFieldType(field)
|
||||||
return if(fieldDt==null)
|
return if(fieldDt==null)
|
||||||
|
|||||||
@@ -93,27 +93,10 @@ object InferredTypes {
|
|||||||
else -> throw IllegalArgumentException("invalid sub type")
|
else -> throw IllegalArgumentException("invalid sub type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type.isPointerArray -> {
|
type.isPointerArray -> InferredType.known(type)
|
||||||
InferredType.known(DataType.arrayOfPointersTo(type.sub, type.subType))
|
type.isArray -> InferredType.known(type)
|
||||||
}
|
type.isPointer -> InferredType.known(type)
|
||||||
type.isArray -> {
|
type.isStructInstance -> InferredType.known(type)
|
||||||
InferredType.known(DataType.arrayFor(type.sub!!, false))
|
|
||||||
}
|
|
||||||
type.isPointer -> {
|
|
||||||
if(type.subType!=null)
|
|
||||||
InferredType.known(DataType.pointerToType(type.subType!!))
|
|
||||||
else if(type.sub!=null)
|
|
||||||
InferredType.known(DataType.pointer(type.sub!!))
|
|
||||||
else
|
|
||||||
InferredType.known(DataType.pointerFromAntlr(type.subTypeFromAntlr!!))
|
|
||||||
}
|
|
||||||
type.isPointerArray -> InferredType.known(DataType.arrayOfPointersTo(type.sub, type.subType))
|
|
||||||
type.isStructInstance -> {
|
|
||||||
if(type.subType!=null)
|
|
||||||
InferredType.known(DataType.structInstance(type.subType!!))
|
|
||||||
else
|
|
||||||
InferredType.known(DataType.structInstanceFromAntlr(type.subTypeFromAntlr!!))
|
|
||||||
}
|
|
||||||
else -> throw IllegalArgumentException("invalid type $type")
|
else -> throw IllegalArgumentException("invalid type $type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ main {
|
|||||||
sub start() {
|
sub start() {
|
||||||
^^List l1 = List()
|
^^List l1 = List()
|
||||||
cx16.r0= l1.s[2]
|
cx16.r0= l1.s[2]
|
||||||
l1.s[10] = 2
|
l1.s[2] = cx16.r1L
|
||||||
|
|
||||||
|
|
||||||
|
; l1.s^^ = 2 TODO fix undefined symbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -617,14 +617,14 @@ class IRFileReader {
|
|||||||
if(isArray) {
|
if(isArray) {
|
||||||
if(type[0]=='^') {
|
if(type[0]=='^') {
|
||||||
return when(type.drop(1)) {
|
return when(type.drop(1)) {
|
||||||
"bool" -> DataType.arrayOfPointersTo(BaseDataType.BOOL, null)
|
"bool" -> DataType.arrayOfPointersTo(BaseDataType.BOOL)
|
||||||
"byte" -> DataType.arrayOfPointersTo(BaseDataType.BYTE, null)
|
"byte" -> DataType.arrayOfPointersTo(BaseDataType.BYTE)
|
||||||
"ubyte", "str" -> DataType.arrayOfPointersTo(BaseDataType.UBYTE, null)
|
"ubyte", "str" -> DataType.arrayOfPointersTo(BaseDataType.UBYTE)
|
||||||
"word" -> DataType.arrayOfPointersTo(BaseDataType.WORD, null)
|
"word" -> DataType.arrayOfPointersTo(BaseDataType.WORD)
|
||||||
"uword" -> DataType.arrayOfPointersTo(BaseDataType.UWORD, null)
|
"uword" -> DataType.arrayOfPointersTo(BaseDataType.UWORD)
|
||||||
"float" -> DataType.arrayOfPointersTo(BaseDataType.FLOAT, null)
|
"float" -> DataType.arrayOfPointersTo(BaseDataType.FLOAT)
|
||||||
"long" -> DataType.arrayOfPointersTo(BaseDataType.LONG, null)
|
"long" -> DataType.arrayOfPointersTo(BaseDataType.LONG)
|
||||||
else -> DataType.arrayOfPointersTo(null, IRSubtypePlaceholder(type.drop(1)))
|
else -> DataType.arrayOfPointersTo(IRSubtypePlaceholder(type.drop(1)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return when(type) {
|
return when(type) {
|
||||||
@@ -651,7 +651,7 @@ class IRFileReader {
|
|||||||
"float" -> DataType.pointer(BaseDataType.FLOAT)
|
"float" -> DataType.pointer(BaseDataType.FLOAT)
|
||||||
"long" -> DataType.pointer(BaseDataType.LONG)
|
"long" -> DataType.pointer(BaseDataType.LONG)
|
||||||
// note: 'str' should not occur anymore in IR. Should be 'uword'
|
// note: 'str' should not occur anymore in IR. Should be 'uword'
|
||||||
else -> DataType.pointerToType(IRSubtypePlaceholder(type.drop(1)))
|
else -> DataType.pointer(IRSubtypePlaceholder(type.drop(1)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return when(type) {
|
return when(type) {
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
|
|||||||
is PtRange -> true
|
is PtRange -> true
|
||||||
is PtString -> true
|
is PtString -> true
|
||||||
is PtPointerDeref -> this.startpointer.isSimple() && this.field==null && this.chain.isEmpty()
|
is PtPointerDeref -> this.startpointer.isSimple() && this.field==null && this.chain.isEmpty()
|
||||||
is PtPointerIndexedDeref -> this.indexer.isSimple()
|
is PtPointerIndexedDeref -> this.index.isSimple()
|
||||||
is PtTypeCast -> value.isSimple()
|
is PtTypeCast -> value.isSimple()
|
||||||
is PtIfExpression -> condition.isSimple() && truevalue.isSimple() && falsevalue.isSimple()
|
is PtIfExpression -> condition.isSimple() && truevalue.isSimple() && falsevalue.isSimple()
|
||||||
}
|
}
|
||||||
@@ -415,8 +415,10 @@ class PtPointerDeref(type: DataType, val chain: List<String>, val field: String?
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PtPointerIndexedDeref(type: DataType, position: Position) : PtExpression(type, position) {
|
class PtPointerIndexedDeref(type: DataType, position: Position) : PtExpression(type, position) {
|
||||||
val indexer: PtArrayIndexer
|
val variable: PtIdentifier
|
||||||
get() = children.single() as PtArrayIndexer
|
get() = children[0] as PtIdentifier
|
||||||
|
val index: PtExpression
|
||||||
|
get() = children[1] as PtExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
// special node that isn't created from compiling user code, but used internally in the Intermediate Code
|
// special node that isn't created from compiling user code, but used internally in the Intermediate Code
|
||||||
|
|||||||
Reference in New Issue
Block a user