mirror of
https://github.com/irmen/prog8.git
synced 2025-09-27 07:17:01 +00:00
preparing for statically allocating struct instances
This commit is contained in:
@@ -629,6 +629,10 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
if(fcall?.target?.targetStructDecl()!=null)
|
||||
// Struct(...) initializer
|
||||
return super.visit(assignment)
|
||||
|
||||
// unfortunately the AST regarding pointer dereferencing is a bit of a mess, and we cannot do precise type checking on elements inside such expressions yet.
|
||||
if(assignment.value.inferType(program).isUnknown) {
|
||||
val binexpr = assignment.value as? BinaryExpression
|
||||
@@ -2213,7 +2217,7 @@ internal class AstChecker(private val program: Program,
|
||||
if(sourceDatatype.isPointer) {
|
||||
if(!(sourceDatatype isAssignableTo targetDatatype))
|
||||
errors.err("cannot assign different pointer type", position)
|
||||
} else if(!sourceDatatype.isUnsignedWord)
|
||||
} else if(!sourceDatatype.isUnsignedWord && !sourceDatatype.isStructInstance)
|
||||
errors.err("can only assign uword or correct pointer type to a pointer", position)
|
||||
}
|
||||
else if(targetDatatype.isString && sourceDatatype.isUnsignedWord)
|
||||
|
@@ -227,7 +227,7 @@ internal fun IdentifierReference.checkFunctionOrLabelExists(program: Program, st
|
||||
else
|
||||
errors.err("cannot call that: ${this.nameInSource.joinToString(".")}", this.position)
|
||||
}
|
||||
is Alias -> {
|
||||
is Alias, is StructDecl -> {
|
||||
return targetStatement
|
||||
}
|
||||
null -> {
|
||||
|
@@ -252,7 +252,7 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
||||
if(target.type!=VarDeclType.VAR || !target.datatype.isUnsignedWord)
|
||||
errors.err("wrong address variable datatype, expected uword", call.target.position)
|
||||
}
|
||||
is Alias -> {}
|
||||
is Alias, is StructDecl -> {}
|
||||
null -> {}
|
||||
else -> errors.err("cannot call this as a subroutine or function", call.target.position)
|
||||
}
|
||||
|
@@ -366,7 +366,17 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
|
||||
val (target, _) = srcCall.target.targetNameAndType(program)
|
||||
val iType = srcCall.inferType(program)
|
||||
val call = PtFunctionCall(target, iType.isUnknown && srcCall.parent !is Assignment, iType.getOrElse { DataType.UNDEFINED }, srcCall.position)
|
||||
val call =
|
||||
if(iType.isStructInstance) {
|
||||
// a call to a struct yields a struct instance and means: allocate a statically initialized struct instance of that type
|
||||
val struct = iType.getOrUndef().subType!!
|
||||
val pointertype = DataType.pointerToType(struct)
|
||||
PtBuiltinFunctionCall("staticalloc", false, true, pointertype, srcCall.position)
|
||||
} else {
|
||||
// regular function call
|
||||
PtFunctionCall(target, iType.isUnknown && srcCall.parent !is Assignment, iType.getOrElse { DataType.UNDEFINED }, srcCall.position)
|
||||
}
|
||||
|
||||
for (arg in srcCall.args)
|
||||
call.add(transformExpression(arg))
|
||||
return call
|
||||
|
@@ -9,11 +9,11 @@ import prog8.code.core.*
|
||||
|
||||
internal fun postprocessSimplifiedAst(program: PtProgram, st: SymbolTable, errors: IErrorReporter) {
|
||||
processDefers(program, st, errors)
|
||||
processSubtypes(program, st)
|
||||
processSubtypesIntoStReferences(program, st)
|
||||
}
|
||||
|
||||
|
||||
private fun processSubtypes(program: PtProgram, st: SymbolTable) {
|
||||
private fun processSubtypesIntoStReferences(program: PtProgram, st: SymbolTable) {
|
||||
|
||||
fun getStStruct(subType: ISubType): StStruct {
|
||||
val stNode = st.lookup(subType.scopedNameString) as? StStruct
|
||||
|
@@ -1433,6 +1433,9 @@ class FunctionCallExpression(override var target: IdentifierReference,
|
||||
|
||||
return InferredTypes.unknown() // has multiple return types... so not a single resulting datatype possible
|
||||
}
|
||||
is StructDecl -> {
|
||||
return InferredTypes.knownFor(DataType.structInstance(stmt))
|
||||
}
|
||||
else -> return InferredTypes.unknown()
|
||||
}
|
||||
}
|
||||
|
@@ -28,14 +28,16 @@ STRUCTS and TYPED POINTERS
|
||||
- DONE (for basic types only): allow array syntax on pointers too: ptr[2] means ptr+sizeof()*2, ptr[0] just means ptr^^ .
|
||||
- DONE (?) allow array syntax on pointers to structs too, but what type will ptr[2] have? And it will require ptr[2].field to work as well now. Actually that will be the only thing to work for now.
|
||||
- DONE: allow multi-field declarations in structs
|
||||
- is the ARRAY_POINTER data type enum realy needed? can just use ARRAY?
|
||||
- are the ARRAY_POINTER and ARRAY_STRUCT data type enums realy needed? can just use ARRAY?
|
||||
- pointer types in subroutine signatures (both normal and asm-subs)
|
||||
- support chaining pointer dereference on function calls that return a pointer. (type checking now fails on stuff like func().field and func().next.field)
|
||||
- pointer arithmetic should follow C: ptr=ptr+10 adds 10*sizeof() instead of just 10.
|
||||
- fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator"
|
||||
- add unit tests for all changes
|
||||
- arrays of structs? No -> Just an array of uword pointers to said structs. Can even be @split as the only representation form because that's the default for word arrays.
|
||||
- static initialization of structs may be allowed only at block scope and then behaves like arrays; it won't reset to the original value when program is restarted, so beware. Syntax = TBD
|
||||
- static initialization of structs may be allowed only at block scope and then behaves like arrays; it won't reset to the original value when program is restarted, so beware.
|
||||
Syntax could be: ^^Node ptr = Node(1,2,3,4) statically allocates a Node with fields set to 1,2,3,4 and puts the address in ptr.
|
||||
- Verify the argments to such a static struct initializer 'call' against the fields, and the same check as for static array values (const value or address-of) ?
|
||||
- allow memory-mapped structs? Something like &Sprite sprite0 = $9000 basically behaves identically to a typed pointer, but the address is immutable as usual
|
||||
- existing STR and ARRAY remain unchanged (don't become typed pointers) so we can keep doing register-indexed addressing directly on them
|
||||
- rather than str or uword parameter types for routines with a string argument, use ^^str (or ^^ubyte maybe? these are more or less identical..?)
|
||||
|
@@ -16,10 +16,10 @@ main {
|
||||
^^Node next
|
||||
}
|
||||
|
||||
Node @shared node1,node2,node3
|
||||
node1.value = 42
|
||||
node1.value2 = 55
|
||||
node1.value3 = 66
|
||||
; proposed static initializer syntax:
|
||||
; ^^Node @shared node3 = Node( 33,2,3, 0 )
|
||||
; ^^Node @shared node2 = Node( 22,2,3, &node3 )
|
||||
; ^^Node @shared node1 = Node( 11,2,3, &node2 )
|
||||
|
||||
^^Node n0,n1,n2,n3,n4,n5,n6,n7,n8
|
||||
|
||||
|
@@ -253,15 +253,15 @@ class StMemVar(name: String,
|
||||
|
||||
class StStruct(
|
||||
name: String,
|
||||
val members: List<Pair<DataType, String>>,
|
||||
val fields: List<Pair<DataType, String>>,
|
||||
astNode: PtStructDecl?
|
||||
) : StNode(name, StNodeType.STRUCT, astNode), ISubType {
|
||||
|
||||
fun memsize(sizer: IMemSizer): Int = members.sumOf { sizer.memorySize(it.first, 1) }
|
||||
fun memsize(sizer: IMemSizer): Int = fields.sumOf { sizer.memorySize(it.first, 1) }
|
||||
fun getField(name: String, sizer: IMemSizer): Pair<DataType, Int> {
|
||||
// returns type and byte offset of the given field
|
||||
var offset = 0
|
||||
for((dt, definedname) in members) {
|
||||
for((dt, definedname) in fields) {
|
||||
if(name==definedname)
|
||||
return dt to offset
|
||||
offset += sizer.memorySize(dt, null)
|
||||
|
@@ -120,6 +120,10 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
|
||||
// don't add memory slabs in nested scope, just put them in the top level of the ST
|
||||
scope.first().add(StMemorySlab("prog8_memoryslab_$slabname", size, align, node))
|
||||
}
|
||||
else if(node.name=="staticalloc") {
|
||||
val struct = node.type.subType!!
|
||||
TODO("symboltable alloc and initialize static struct ${struct.scopedNameString}")
|
||||
}
|
||||
null
|
||||
}
|
||||
else -> null // node is not present in the ST
|
||||
|
@@ -46,8 +46,12 @@ fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Uni
|
||||
is PtArrayIndexer -> "<arrayindexer> ${type(node.type)} ${if(node.splitWords) "[splitwords]" else ""}"
|
||||
is PtBinaryExpression -> "<expr> ${node.operator} ${type(node.type)}"
|
||||
is PtBuiltinFunctionCall -> {
|
||||
val str = if(node.void) "void " else ""
|
||||
str + node.name + "()"
|
||||
if(node.name=="staticalloc") {
|
||||
node.type.subType!!.scopedNameString+"()"
|
||||
} else {
|
||||
val str = if (node.void) "void " else ""
|
||||
str + node.name + "()"
|
||||
}
|
||||
}
|
||||
is PtContainmentCheck -> "in"
|
||||
is PtFunctionCall -> {
|
||||
|
Reference in New Issue
Block a user