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.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 =
|
||||
DataType(BaseDataType.ARRAY_POINTER, sub, subType)
|
||||
fun arrayOfPointersTo(sub: BaseDataType): DataType = DataType(BaseDataType.ARRAY_POINTER, sub, null)
|
||||
fun arrayOfPointersTo(structType: ISubType?): DataType = DataType(BaseDataType.ARRAY_POINTER, null, structType)
|
||||
fun arrayOfPointersFromAntlrTo(sub: BaseDataType?, identifier: List<String>?): DataType =
|
||||
DataType(BaseDataType.ARRAY_POINTER, sub, null, identifier)
|
||||
|
||||
fun pointer(base: BaseDataType): DataType = DataType(BaseDataType.POINTER, base, null)
|
||||
fun pointerToType(type: ISubType): DataType = DataType(BaseDataType.POINTER, null, type)
|
||||
fun structInstance(type: ISubType?): DataType = DataType(BaseDataType.STRUCT_INSTANCE, sub=null, type)
|
||||
fun pointer(dt: DataType): DataType {
|
||||
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 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)
|
||||
}
|
||||
|
||||
@@ -184,10 +194,10 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
|
||||
return pointer(BaseDataType.UBYTE)
|
||||
val elementDt = elementType()
|
||||
require(elementDt.isBasic)
|
||||
return pointer(elementDt.base)
|
||||
return pointer(elementDt)
|
||||
}
|
||||
if (subType != null)
|
||||
return pointerToType(subType!!)
|
||||
return pointer(this)
|
||||
return UWORD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,25 +98,28 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
|
||||
private fun translate(idxderef: PtPointerIndexedDeref): ExpressionCodeResult {
|
||||
val idx = idxderef.indexer
|
||||
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")
|
||||
|
||||
val eltSize = codeGen.program.memsizer.memorySize(idxderef.type, null)
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val pointerTr = translateExpression(idx.variable)
|
||||
result += pointerTr.chunks
|
||||
val pointerReg = pointerTr.resultReg
|
||||
val constIndex = idx.index.asConstInteger()
|
||||
if(!idxderef.variable.type.isPointer) {
|
||||
TODO("expression: indexing non-pointer field ${idxderef.variable}")
|
||||
}
|
||||
|
||||
TODO("evaluate address of pointer dereference ${idxderef.position}")
|
||||
|
||||
val pointerReg = -1 // pointerTr.resultReg
|
||||
val constIndex = idxderef.index.asConstInteger()
|
||||
if(constIndex!=null) {
|
||||
val offset = constIndex * eltSize
|
||||
addInstr(result, IRInstruction(Opcode.ADD, IRDataType.WORD, reg1 = pointerReg, immediate = offset), null)
|
||||
} else {
|
||||
val indexTr = translateExpression(idx.index)
|
||||
val indexTr = translateExpression(idxderef.index)
|
||||
result += indexTr.chunks
|
||||
result += IRCodeChunk(null, null).also {
|
||||
val indexReg: Int
|
||||
if (idx.index.type.isByte) {
|
||||
if (idxderef.index.type.isByte) {
|
||||
// extend array index to word
|
||||
indexReg = codeGen.registers.next(IRDataType.WORD)
|
||||
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 {
|
||||
throw FatalAstException("unknown dt")
|
||||
}
|
||||
require(type.isPointer || type.isUnsignedWord)
|
||||
if(type.isUnsignedWord) {
|
||||
if(idxderef.parent is AssignTarget)
|
||||
TODO("as assignment target: indexing uword field $idxderef") // TODO hmm, wasn't there code elsewhere for this already?
|
||||
else
|
||||
TODO("as value: indexing uword field $idxderef") // TODO hmm, wasn't there code elsewhere for this already?
|
||||
} 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
|
||||
}
|
||||
val derefType = if(type.isPointer) DataType.forDt(type.sub!!) else type
|
||||
val deref = PtPointerIndexedDeref(derefType, idxderef.position)
|
||||
val identifier = PtIdentifier(idxderef.indexed.arrayvar.nameInSource.joinToString("."), DataType.pointer(derefType), idxderef.indexed.arrayvar.position)
|
||||
deref.add(identifier)
|
||||
deref.add(transformExpression(idxderef.indexed.indexer.indexExpr))
|
||||
return deref
|
||||
}
|
||||
|
||||
private fun transform(deref: PtrDereference): PtPointerDeref {
|
||||
@@ -411,8 +402,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
val call =
|
||||
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
|
||||
val pointertype = DataType.pointerToType(targetStruct)
|
||||
PtBuiltinFunctionCall("structalloc", false, true, pointertype, srcCall.position)
|
||||
PtBuiltinFunctionCall("structalloc", false, true, DataType.pointer(targetStruct), srcCall.position)
|
||||
} else {
|
||||
// regular function call
|
||||
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 {
|
||||
val eltDt = decl.datatype.elementType()
|
||||
if(eltDt.isPointer)
|
||||
DataType.arrayOfPointersTo(eltDt.base, eltDt.subType)
|
||||
TODO("convert array of pointers to split words array type")
|
||||
else
|
||||
DataType.arrayFor(eltDt.base)
|
||||
}
|
||||
@@ -95,7 +95,7 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
changeDataType = if(decl.datatype.isSplitWordArray) null else {
|
||||
val eltDt = decl.datatype.elementType()
|
||||
if(eltDt.isPointer)
|
||||
DataType.arrayOfPointersTo(eltDt.base, eltDt.subType)
|
||||
TODO("convert array of pointers to split words array type")
|
||||
else
|
||||
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, 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.pointer(BaseDataType.BOOL).typeForAddressOf(false) shouldBe DataType.UWORD
|
||||
|
||||
@@ -1093,7 +1093,10 @@ class ArrayLiteral(val type: InferredTypes.InferredType, // inferred because
|
||||
val unique = dts.toSet()
|
||||
if(unique.size==1) {
|
||||
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 {
|
||||
@@ -1474,7 +1477,7 @@ class FunctionCallExpression(override var target: IdentifierReference,
|
||||
}
|
||||
is StructDecl -> {
|
||||
// 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()
|
||||
}
|
||||
@@ -1691,7 +1694,7 @@ class PtrDereference(val identifier: IdentifierReference, val chain: List<String
|
||||
struct = fieldDt.subType as StructDecl
|
||||
}
|
||||
if(field==null) {
|
||||
return InferredTypes.knownFor(DataType.pointerToType(struct))
|
||||
return InferredTypes.knownFor(DataType.pointer(struct))
|
||||
}
|
||||
val fieldDt = struct.getFieldType(field)
|
||||
return if(fieldDt==null)
|
||||
|
||||
@@ -93,27 +93,10 @@ object InferredTypes {
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
type.isPointerArray -> {
|
||||
InferredType.known(DataType.arrayOfPointersTo(type.sub, type.subType))
|
||||
}
|
||||
type.isArray -> {
|
||||
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!!))
|
||||
}
|
||||
type.isPointerArray -> InferredType.known(type)
|
||||
type.isArray -> InferredType.known(type)
|
||||
type.isPointer -> InferredType.known(type)
|
||||
type.isStructInstance -> InferredType.known(type)
|
||||
else -> throw IllegalArgumentException("invalid type $type")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ main {
|
||||
sub start() {
|
||||
^^List l1 = List()
|
||||
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(type[0]=='^') {
|
||||
return when(type.drop(1)) {
|
||||
"bool" -> DataType.arrayOfPointersTo(BaseDataType.BOOL, null)
|
||||
"byte" -> DataType.arrayOfPointersTo(BaseDataType.BYTE, null)
|
||||
"ubyte", "str" -> DataType.arrayOfPointersTo(BaseDataType.UBYTE, null)
|
||||
"word" -> DataType.arrayOfPointersTo(BaseDataType.WORD, null)
|
||||
"uword" -> DataType.arrayOfPointersTo(BaseDataType.UWORD, null)
|
||||
"float" -> DataType.arrayOfPointersTo(BaseDataType.FLOAT, null)
|
||||
"long" -> DataType.arrayOfPointersTo(BaseDataType.LONG, null)
|
||||
else -> DataType.arrayOfPointersTo(null, IRSubtypePlaceholder(type.drop(1)))
|
||||
"bool" -> DataType.arrayOfPointersTo(BaseDataType.BOOL)
|
||||
"byte" -> DataType.arrayOfPointersTo(BaseDataType.BYTE)
|
||||
"ubyte", "str" -> DataType.arrayOfPointersTo(BaseDataType.UBYTE)
|
||||
"word" -> DataType.arrayOfPointersTo(BaseDataType.WORD)
|
||||
"uword" -> DataType.arrayOfPointersTo(BaseDataType.UWORD)
|
||||
"float" -> DataType.arrayOfPointersTo(BaseDataType.FLOAT)
|
||||
"long" -> DataType.arrayOfPointersTo(BaseDataType.LONG)
|
||||
else -> DataType.arrayOfPointersTo(IRSubtypePlaceholder(type.drop(1)))
|
||||
}
|
||||
}
|
||||
return when(type) {
|
||||
@@ -651,7 +651,7 @@ class IRFileReader {
|
||||
"float" -> DataType.pointer(BaseDataType.FLOAT)
|
||||
"long" -> DataType.pointer(BaseDataType.LONG)
|
||||
// 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) {
|
||||
|
||||
@@ -116,7 +116,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
|
||||
is PtRange -> true
|
||||
is PtString -> true
|
||||
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 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) {
|
||||
val indexer: PtArrayIndexer
|
||||
get() = children.single() as PtArrayIndexer
|
||||
val variable: PtIdentifier
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user