mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 23:29:55 +00:00
prepare
This commit is contained in:
parent
1e9586f635
commit
9f6fa60bf1
@ -231,11 +231,7 @@ class ArrayIndexedExpression(val identifier: IdentifierReference,
|
||||
return when (target.datatype) {
|
||||
in NumericDatatypes -> null
|
||||
in StringDatatypes -> DataType.UBYTE
|
||||
DataType.ARRAY_UB -> DataType.UBYTE
|
||||
DataType.ARRAY_B -> DataType.BYTE
|
||||
DataType.ARRAY_UW -> DataType.UWORD
|
||||
DataType.ARRAY_W -> DataType.WORD
|
||||
DataType.ARRAY_F -> DataType.FLOAT
|
||||
in ArrayDatatypes -> ArrayElementTypes[target.datatype]
|
||||
else -> throw FatalAstException("invalid dt")
|
||||
}
|
||||
}
|
||||
|
@ -406,11 +406,13 @@ internal class AstChecker(private val program: Program,
|
||||
if(targetDatatype!=null) {
|
||||
val constVal = assignment.value.constValue(program)
|
||||
if(constVal!=null) {
|
||||
val arrayspec = if(target.identifier!=null) {
|
||||
val targetVar = program.namespace.lookup(target.identifier.nameInSource, assignment) as? VarDecl
|
||||
targetVar?.arraysize
|
||||
} else null
|
||||
checkValueTypeAndRange(targetDatatype,
|
||||
val targetVar =
|
||||
if(target.identifier!=null)
|
||||
program.namespace.lookup(target.identifier.nameInSource, assignment) as? VarDecl
|
||||
else
|
||||
null
|
||||
val arrayspec = if(target.identifier!=null) targetVar?.arraysize else null
|
||||
checkValueTypeAndRange(targetDatatype, targetVar?.struct,
|
||||
arrayspec ?: ArrayIndex(LiteralValue.optimalInteger(-1, assignment.position), assignment.position),
|
||||
constVal, program.heap)
|
||||
} else {
|
||||
@ -424,8 +426,9 @@ internal class AstChecker(private val program: Program,
|
||||
else
|
||||
checkResult.add(ExpressionError("assignment value is invalid or has no proper datatype", assignment.value.position))
|
||||
}
|
||||
else
|
||||
checkAssignmentCompatible(targetDatatype, sourceDatatype, assignment.value, target, assignment.position)
|
||||
else {
|
||||
checkAssignmentCompatible(targetDatatype, target, sourceDatatype, assignment.value, assignment.position)
|
||||
}
|
||||
}
|
||||
}
|
||||
return assignment
|
||||
@ -521,7 +524,7 @@ internal class AstChecker(private val program: Program,
|
||||
else
|
||||
ArrayIndex(LiteralValue.optimalInteger(-2, decl.position), decl.position)
|
||||
)
|
||||
checkValueTypeAndRange(decl.datatype, arraySpec, decl.value as LiteralValue, program.heap)
|
||||
checkValueTypeAndRange(decl.datatype, decl.struct, arraySpec, decl.value as LiteralValue, program.heap)
|
||||
}
|
||||
else -> {
|
||||
err("var/const declaration needs a compile-time constant initializer value, or range, instead found: ${decl.value!!.javaClass.simpleName}")
|
||||
@ -664,7 +667,7 @@ internal class AstChecker(private val program: Program,
|
||||
ArrayIndex.forArray(literalValue, program.heap)
|
||||
else
|
||||
ArrayIndex(LiteralValue.optimalInteger(-3, literalValue.position), literalValue.position)
|
||||
checkValueTypeAndRange(literalValue.type, arrayspec, literalValue, program.heap)
|
||||
checkValueTypeAndRange(literalValue.type, null, arrayspec, literalValue, program.heap)
|
||||
|
||||
val lv = super.visit(literalValue)
|
||||
when(lv.type) {
|
||||
@ -1009,7 +1012,8 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkValueTypeAndRange(targetDt: DataType, arrayspec: ArrayIndex, value: LiteralValue, heap: HeapValues) : Boolean {
|
||||
private fun checkValueTypeAndRange(targetDt: DataType, struct: StructDecl?,
|
||||
arrayspec: ArrayIndex, value: LiteralValue, heap: HeapValues) : Boolean {
|
||||
fun err(msg: String) : Boolean {
|
||||
checkResult.add(ExpressionError(msg, value.position))
|
||||
return false
|
||||
@ -1138,9 +1142,20 @@ internal class AstChecker(private val program: Program,
|
||||
return err("invalid float array initialization value ${value.type}, expected $targetDt")
|
||||
}
|
||||
DataType.STRUCT -> {
|
||||
if(value.type!=DataType.STRUCT)
|
||||
return err("cannot assign a normal value to a struct")
|
||||
TODO("check struct, $value ")
|
||||
if(value.type in ArrayDatatypes) {
|
||||
if(value.arrayvalue!!.size != struct!!.numberOfElements)
|
||||
return err("number of values is not the same as the number of members in the struct")
|
||||
for(elt in value.arrayvalue.zip(struct.statements)) {
|
||||
val vardecl = elt.second as VarDecl
|
||||
val valuetype = elt.first.inferType(program)!!
|
||||
if (!(valuetype isAssignableTo vardecl.datatype)) {
|
||||
checkResult.add(ExpressionError("invalid struct member init value type $valuetype, expected ${vardecl.datatype}", elt.first.position))
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
@ -1196,9 +1211,9 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
private fun checkAssignmentCompatible(targetDatatype: DataType,
|
||||
target: AssignTarget,
|
||||
sourceDatatype: DataType,
|
||||
sourceValue: IExpression,
|
||||
target: AssignTarget,
|
||||
position: Position) : Boolean {
|
||||
|
||||
if(sourceValue is RangeExpr)
|
||||
@ -1214,6 +1229,13 @@ internal class AstChecker(private val program: Program,
|
||||
DataType.STR_S -> sourceDatatype== DataType.STR_S
|
||||
DataType.STRUCT -> {
|
||||
// for now we've decided you cannot assign struct by-value.
|
||||
// but you can however assign an array to it of the correct size
|
||||
if(sourceDatatype in ArrayDatatypes) {
|
||||
val identifier = sourceValue as IdentifierReference
|
||||
val sourceArraySize = identifier.targetVarDecl(program.namespace)!!.arraysize?.size()
|
||||
val targetstruct = target.identifier!!.targetVarDecl(program.namespace)!!.struct!!
|
||||
return targetstruct.numberOfElements == sourceArraySize
|
||||
}
|
||||
// if(sourceDatatype==DataType.STRUCT) {
|
||||
// val sourcename = (sourceValue as IdentifierReference).nameInSource
|
||||
// val vd1 = program.namespace.lookup(sourcename, target) as? VarDecl
|
||||
|
@ -223,8 +223,15 @@ internal class AstIdentifiersChecker(private val namespace: INameScope) : IAstMo
|
||||
// a literal value that's not declared as a variable, which refers to something on the heap.
|
||||
// we need to introduce an auto-generated variable for this to be able to refer to the value!
|
||||
// (note: ususally, this has been taken care of already when the var was created)
|
||||
val variable = VarDecl(VarDeclType.VAR, literalValue.type, false, null, "$autoHeapValuePrefix${literalValue.heapId}", null, literalValue,
|
||||
isArray = false, hiddenButDoNotRemove = false, position = literalValue.position)
|
||||
val declaredType = if(literalValue.isArray) ArrayElementTypes.getValue(literalValue.type) else literalValue.type
|
||||
val variable = VarDecl(VarDeclType.VAR,
|
||||
declaredType,
|
||||
false,
|
||||
null,
|
||||
"$autoHeapValuePrefix${literalValue.heapId}",
|
||||
null,
|
||||
literalValue,
|
||||
isArray = literalValue.isArray, hiddenButDoNotRemove = true, position = literalValue.position)
|
||||
anonymousVariablesFromHeap[variable.name] = Pair(literalValue, variable)
|
||||
}
|
||||
return super.visit(literalValue)
|
||||
|
@ -6,6 +6,7 @@ import prog8.ast.expressions.*
|
||||
import prog8.ast.processing.IAstModifyingVisitor
|
||||
import prog8.ast.processing.IAstVisitor
|
||||
import prog8.compiler.HeapValues
|
||||
import prog8.compiler.target.c64.Mflpt5
|
||||
|
||||
|
||||
class BuiltinFunctionStatementPlaceholder(val name: String, override val position: Position) : IStatement {
|
||||
@ -162,7 +163,7 @@ class VarDecl(val type: VarDeclType,
|
||||
DataType.FLOAT -> DataType.ARRAY_F
|
||||
else -> {
|
||||
datatypeErrors.add(SyntaxError("array can only contain bytes/words/floats", position))
|
||||
DataType.UBYTE
|
||||
DataType.ARRAY_UB
|
||||
}
|
||||
}
|
||||
|
||||
@ -740,6 +741,22 @@ class StructDecl(override val name: String,
|
||||
this.statements.forEach { it.linkParents(this) }
|
||||
}
|
||||
|
||||
val numberOfElements: Int
|
||||
get() = this.statements.size
|
||||
val memorySize: Int
|
||||
get() = this.statements.map {
|
||||
val decl = it as VarDecl
|
||||
when {
|
||||
decl.datatype in ByteDatatypes -> 8
|
||||
decl.datatype in WordDatatypes -> 16
|
||||
decl.datatype==DataType.FLOAT -> Mflpt5.MemorySize
|
||||
decl.datatype in StringDatatypes -> TODO("stringvalue size")
|
||||
decl.datatype in ArrayDatatypes -> decl.arraysize!!.size()!!
|
||||
decl.datatype==DataType.STRUCT -> decl.struct!!.memorySize
|
||||
else -> throw FatalAstException("can't get size for $decl")
|
||||
}
|
||||
}.sum()
|
||||
|
||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||
override fun accept(visitor: IAstModifyingVisitor) = visitor.visit(this)
|
||||
}
|
||||
|
@ -103,10 +103,10 @@ class AstToSourceCode(val output: (text: String) -> Unit): IAstVisitor {
|
||||
}
|
||||
|
||||
override fun visit(decl: VarDecl) {
|
||||
if(decl.hiddenButDoNotRemove) {
|
||||
// skip autogenerated vardecl
|
||||
return
|
||||
}
|
||||
// if(decl.hiddenButDoNotRemove) {
|
||||
// // skip autogenerated vardecl
|
||||
// return
|
||||
// }
|
||||
|
||||
when(decl.type) {
|
||||
VarDeclType.VAR -> {}
|
||||
@ -114,6 +114,7 @@ class AstToSourceCode(val output: (text: String) -> Unit): IAstVisitor {
|
||||
VarDeclType.MEMORY -> output("&")
|
||||
VarDeclType.STRUCT -> output("${decl.struct!!.name} ")
|
||||
}
|
||||
output(decl.struct?.name ?: "")
|
||||
output(datatypeString(decl.datatype))
|
||||
if(decl.arraysize!=null) {
|
||||
decl.arraysize!!.index.accept(this)
|
||||
|
@ -1446,6 +1446,27 @@ internal class Compiler(private val program: Program) {
|
||||
else -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||
}
|
||||
}
|
||||
DataType.STRUCT -> {
|
||||
// Assume the value is an array. Flatten the struct assignment into memberwise assignments.
|
||||
val identifier = stmt.target.identifier!!
|
||||
val identifierName = identifier.nameInSource.single()
|
||||
val targetVar = identifier.targetVarDecl(program.namespace)!!
|
||||
val struct = targetVar.struct!!
|
||||
val sourceVar = (stmt.value as IdentifierReference).targetVarDecl(program.namespace)!!
|
||||
if(!sourceVar.isArray)
|
||||
throw CompilerException("can only assign arrays to structs")
|
||||
val sourceArray = (sourceVar.value as LiteralValue).arrayvalue!!
|
||||
for(member in struct.statements.zip(sourceArray)) {
|
||||
val decl = member.first as VarDecl
|
||||
val value = member.second.constValue(program)!!
|
||||
val mangled = mangledStructMemberName(identifierName, decl.name)
|
||||
val idref = IdentifierReference(listOf(mangled), stmt.position)
|
||||
val assign = Assignment(AssignTarget(null, idref, null, null, stmt.position), null, value, value.position)
|
||||
assign.linkParents(stmt)
|
||||
translate(assign)
|
||||
}
|
||||
return
|
||||
}
|
||||
in StringDatatypes -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||
in ArrayDatatypes -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||
else -> throw CompilerException("weird/unknown targetdt")
|
||||
@ -1499,7 +1520,9 @@ internal class Compiler(private val program: Program) {
|
||||
prog.instr(opcode, RuntimeValue(DataType.UWORD, address))
|
||||
}
|
||||
VarDeclType.CONST -> throw CompilerException("cannot assign to const")
|
||||
VarDeclType.STRUCT -> TODO("decltype struct")
|
||||
VarDeclType.STRUCT -> {
|
||||
TODO("decltype struct $assignTarget")
|
||||
}
|
||||
}
|
||||
} else throw CompilerException("invalid assignment target type ${target::class}")
|
||||
}
|
||||
|
@ -175,6 +175,9 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor {
|
||||
decl.value = LiteralValue(decl.datatype, initHeapId = heapId, position = litval.position)
|
||||
}
|
||||
}
|
||||
DataType.STRUCT -> {
|
||||
// leave it alone for structs.
|
||||
}
|
||||
else -> throw FatalAstException("invalid array vardecl type ${decl.datatype}")
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ class VariablesCreator(private val runtimeVariables: RuntimeVariables, private v
|
||||
when (decl.type) {
|
||||
// we can assume the value in the vardecl already has been converted into a constant LiteralValue here.
|
||||
VarDeclType.VAR -> {
|
||||
println("$decl")
|
||||
val value = RuntimeValue.from(decl.value as LiteralValue, heap)
|
||||
runtimeVariables.define(decl.definingScope(), decl.name, value)
|
||||
}
|
||||
|
@ -5,38 +5,49 @@
|
||||
|
||||
sub start() {
|
||||
uword derp
|
||||
ubyte[] v = [22,33,44]
|
||||
|
||||
Color foreground ; = [0,1,2] @todo init values
|
||||
Color background
|
||||
Color cursor
|
||||
Color foreground
|
||||
Color foreground2 = [11,22,33]
|
||||
|
||||
foreground.red=99
|
||||
background.blue=foreground.red
|
||||
|
||||
;cursor=foreground ; @todo full by-value copy
|
||||
|
||||
c64scr.print_ub(foreground.red)
|
||||
c64.CHROUT(':')
|
||||
c64scr.print_ub(foreground.green)
|
||||
c64.CHROUT(':')
|
||||
c64scr.print_ub(foreground.blue)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(background.red)
|
||||
c64.CHROUT(':')
|
||||
c64scr.print_ub(background.green)
|
||||
c64.CHROUT(':')
|
||||
c64scr.print_ub(background.blue)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(cursor.red)
|
||||
c64.CHROUT(':')
|
||||
c64scr.print_ub(cursor.green)
|
||||
c64.CHROUT(':')
|
||||
c64scr.print_ub(cursor.blue)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
return
|
||||
foreground.red = 111
|
||||
; foreground2.red = 111
|
||||
}
|
||||
|
||||
; sub test() {
|
||||
; Color foreground ; = [0,1,2] ;@todo init values
|
||||
; Color background
|
||||
; Color cursor
|
||||
;
|
||||
; foreground.red=99
|
||||
; background.blue=foreground.red
|
||||
;
|
||||
; cursor = [1,2,3] ; assign all members at once
|
||||
; cursor = v
|
||||
; cursor=foreground ; @todo memberwise assignment
|
||||
;
|
||||
; c64scr.print_ub(foreground.red)
|
||||
; c64.CHROUT(':')
|
||||
; c64scr.print_ub(foreground.green)
|
||||
; c64.CHROUT(':')
|
||||
; c64scr.print_ub(foreground.blue)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print_ub(background.red)
|
||||
; c64.CHROUT(':')
|
||||
; c64scr.print_ub(background.green)
|
||||
; c64.CHROUT(':')
|
||||
; c64scr.print_ub(background.blue)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print_ub(cursor.red)
|
||||
; c64.CHROUT(':')
|
||||
; c64scr.print_ub(cursor.green)
|
||||
; c64.CHROUT(':')
|
||||
; c64scr.print_ub(cursor.blue)
|
||||
; c64.CHROUT('\n')
|
||||
;
|
||||
; return
|
||||
; }
|
||||
|
||||
struct Color {
|
||||
ubyte red
|
||||
ubyte green
|
||||
|
Loading…
Reference in New Issue
Block a user