mirror of
https://github.com/irmen/prog8.git
synced 2024-12-27 05:29:38 +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) {
|
return when (target.datatype) {
|
||||||
in NumericDatatypes -> null
|
in NumericDatatypes -> null
|
||||||
in StringDatatypes -> DataType.UBYTE
|
in StringDatatypes -> DataType.UBYTE
|
||||||
DataType.ARRAY_UB -> DataType.UBYTE
|
in ArrayDatatypes -> ArrayElementTypes[target.datatype]
|
||||||
DataType.ARRAY_B -> DataType.BYTE
|
|
||||||
DataType.ARRAY_UW -> DataType.UWORD
|
|
||||||
DataType.ARRAY_W -> DataType.WORD
|
|
||||||
DataType.ARRAY_F -> DataType.FLOAT
|
|
||||||
else -> throw FatalAstException("invalid dt")
|
else -> throw FatalAstException("invalid dt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,11 +406,13 @@ internal class AstChecker(private val program: Program,
|
|||||||
if(targetDatatype!=null) {
|
if(targetDatatype!=null) {
|
||||||
val constVal = assignment.value.constValue(program)
|
val constVal = assignment.value.constValue(program)
|
||||||
if(constVal!=null) {
|
if(constVal!=null) {
|
||||||
val arrayspec = if(target.identifier!=null) {
|
val targetVar =
|
||||||
val targetVar = program.namespace.lookup(target.identifier.nameInSource, assignment) as? VarDecl
|
if(target.identifier!=null)
|
||||||
targetVar?.arraysize
|
program.namespace.lookup(target.identifier.nameInSource, assignment) as? VarDecl
|
||||||
} else null
|
else
|
||||||
checkValueTypeAndRange(targetDatatype,
|
null
|
||||||
|
val arrayspec = if(target.identifier!=null) targetVar?.arraysize else null
|
||||||
|
checkValueTypeAndRange(targetDatatype, targetVar?.struct,
|
||||||
arrayspec ?: ArrayIndex(LiteralValue.optimalInteger(-1, assignment.position), assignment.position),
|
arrayspec ?: ArrayIndex(LiteralValue.optimalInteger(-1, assignment.position), assignment.position),
|
||||||
constVal, program.heap)
|
constVal, program.heap)
|
||||||
} else {
|
} else {
|
||||||
@ -424,8 +426,9 @@ internal class AstChecker(private val program: Program,
|
|||||||
else
|
else
|
||||||
checkResult.add(ExpressionError("assignment value is invalid or has no proper datatype", assignment.value.position))
|
checkResult.add(ExpressionError("assignment value is invalid or has no proper datatype", assignment.value.position))
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
checkAssignmentCompatible(targetDatatype, sourceDatatype, assignment.value, target, assignment.position)
|
checkAssignmentCompatible(targetDatatype, target, sourceDatatype, assignment.value, assignment.position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return assignment
|
return assignment
|
||||||
@ -521,7 +524,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
else
|
else
|
||||||
ArrayIndex(LiteralValue.optimalInteger(-2, decl.position), decl.position)
|
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 -> {
|
else -> {
|
||||||
err("var/const declaration needs a compile-time constant initializer value, or range, instead found: ${decl.value!!.javaClass.simpleName}")
|
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)
|
ArrayIndex.forArray(literalValue, program.heap)
|
||||||
else
|
else
|
||||||
ArrayIndex(LiteralValue.optimalInteger(-3, literalValue.position), literalValue.position)
|
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)
|
val lv = super.visit(literalValue)
|
||||||
when(lv.type) {
|
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 {
|
fun err(msg: String) : Boolean {
|
||||||
checkResult.add(ExpressionError(msg, value.position))
|
checkResult.add(ExpressionError(msg, value.position))
|
||||||
return false
|
return false
|
||||||
@ -1138,9 +1142,20 @@ internal class AstChecker(private val program: Program,
|
|||||||
return err("invalid float array initialization value ${value.type}, expected $targetDt")
|
return err("invalid float array initialization value ${value.type}, expected $targetDt")
|
||||||
}
|
}
|
||||||
DataType.STRUCT -> {
|
DataType.STRUCT -> {
|
||||||
if(value.type!=DataType.STRUCT)
|
if(value.type in ArrayDatatypes) {
|
||||||
return err("cannot assign a normal value to a struct")
|
if(value.arrayvalue!!.size != struct!!.numberOfElements)
|
||||||
TODO("check struct, $value ")
|
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
|
return true
|
||||||
@ -1196,9 +1211,9 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkAssignmentCompatible(targetDatatype: DataType,
|
private fun checkAssignmentCompatible(targetDatatype: DataType,
|
||||||
|
target: AssignTarget,
|
||||||
sourceDatatype: DataType,
|
sourceDatatype: DataType,
|
||||||
sourceValue: IExpression,
|
sourceValue: IExpression,
|
||||||
target: AssignTarget,
|
|
||||||
position: Position) : Boolean {
|
position: Position) : Boolean {
|
||||||
|
|
||||||
if(sourceValue is RangeExpr)
|
if(sourceValue is RangeExpr)
|
||||||
@ -1214,6 +1229,13 @@ internal class AstChecker(private val program: Program,
|
|||||||
DataType.STR_S -> sourceDatatype== DataType.STR_S
|
DataType.STR_S -> sourceDatatype== DataType.STR_S
|
||||||
DataType.STRUCT -> {
|
DataType.STRUCT -> {
|
||||||
// for now we've decided you cannot assign struct by-value.
|
// 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) {
|
// if(sourceDatatype==DataType.STRUCT) {
|
||||||
// val sourcename = (sourceValue as IdentifierReference).nameInSource
|
// val sourcename = (sourceValue as IdentifierReference).nameInSource
|
||||||
// val vd1 = program.namespace.lookup(sourcename, target) as? VarDecl
|
// 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.
|
// 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!
|
// 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)
|
// (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,
|
val declaredType = if(literalValue.isArray) ArrayElementTypes.getValue(literalValue.type) else literalValue.type
|
||||||
isArray = false, hiddenButDoNotRemove = false, position = literalValue.position)
|
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)
|
anonymousVariablesFromHeap[variable.name] = Pair(literalValue, variable)
|
||||||
}
|
}
|
||||||
return super.visit(literalValue)
|
return super.visit(literalValue)
|
||||||
|
@ -6,6 +6,7 @@ import prog8.ast.expressions.*
|
|||||||
import prog8.ast.processing.IAstModifyingVisitor
|
import prog8.ast.processing.IAstModifyingVisitor
|
||||||
import prog8.ast.processing.IAstVisitor
|
import prog8.ast.processing.IAstVisitor
|
||||||
import prog8.compiler.HeapValues
|
import prog8.compiler.HeapValues
|
||||||
|
import prog8.compiler.target.c64.Mflpt5
|
||||||
|
|
||||||
|
|
||||||
class BuiltinFunctionStatementPlaceholder(val name: String, override val position: Position) : IStatement {
|
class BuiltinFunctionStatementPlaceholder(val name: String, override val position: Position) : IStatement {
|
||||||
@ -162,7 +163,7 @@ class VarDecl(val type: VarDeclType,
|
|||||||
DataType.FLOAT -> DataType.ARRAY_F
|
DataType.FLOAT -> DataType.ARRAY_F
|
||||||
else -> {
|
else -> {
|
||||||
datatypeErrors.add(SyntaxError("array can only contain bytes/words/floats", position))
|
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) }
|
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: IAstVisitor) = visitor.visit(this)
|
||||||
override fun accept(visitor: IAstModifyingVisitor) = 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) {
|
override fun visit(decl: VarDecl) {
|
||||||
if(decl.hiddenButDoNotRemove) {
|
// if(decl.hiddenButDoNotRemove) {
|
||||||
// skip autogenerated vardecl
|
// // skip autogenerated vardecl
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
when(decl.type) {
|
when(decl.type) {
|
||||||
VarDeclType.VAR -> {}
|
VarDeclType.VAR -> {}
|
||||||
@ -114,6 +114,7 @@ class AstToSourceCode(val output: (text: String) -> Unit): IAstVisitor {
|
|||||||
VarDeclType.MEMORY -> output("&")
|
VarDeclType.MEMORY -> output("&")
|
||||||
VarDeclType.STRUCT -> output("${decl.struct!!.name} ")
|
VarDeclType.STRUCT -> output("${decl.struct!!.name} ")
|
||||||
}
|
}
|
||||||
|
output(decl.struct?.name ?: "")
|
||||||
output(datatypeString(decl.datatype))
|
output(datatypeString(decl.datatype))
|
||||||
if(decl.arraysize!=null) {
|
if(decl.arraysize!=null) {
|
||||||
decl.arraysize!!.index.accept(this)
|
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")
|
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 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")
|
in ArrayDatatypes -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||||
else -> throw CompilerException("weird/unknown targetdt")
|
else -> throw CompilerException("weird/unknown targetdt")
|
||||||
@ -1499,7 +1520,9 @@ internal class Compiler(private val program: Program) {
|
|||||||
prog.instr(opcode, RuntimeValue(DataType.UWORD, address))
|
prog.instr(opcode, RuntimeValue(DataType.UWORD, address))
|
||||||
}
|
}
|
||||||
VarDeclType.CONST -> throw CompilerException("cannot assign to const")
|
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}")
|
} 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)
|
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}")
|
else -> throw FatalAstException("invalid array vardecl type ${decl.datatype}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,6 @@ class VariablesCreator(private val runtimeVariables: RuntimeVariables, private v
|
|||||||
when (decl.type) {
|
when (decl.type) {
|
||||||
// we can assume the value in the vardecl already has been converted into a constant LiteralValue here.
|
// we can assume the value in the vardecl already has been converted into a constant LiteralValue here.
|
||||||
VarDeclType.VAR -> {
|
VarDeclType.VAR -> {
|
||||||
println("$decl")
|
|
||||||
val value = RuntimeValue.from(decl.value as LiteralValue, heap)
|
val value = RuntimeValue.from(decl.value as LiteralValue, heap)
|
||||||
runtimeVariables.define(decl.definingScope(), decl.name, value)
|
runtimeVariables.define(decl.definingScope(), decl.name, value)
|
||||||
}
|
}
|
||||||
|
@ -5,38 +5,49 @@
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
uword derp
|
uword derp
|
||||||
|
ubyte[] v = [22,33,44]
|
||||||
|
|
||||||
Color foreground ; = [0,1,2] @todo init values
|
Color foreground
|
||||||
Color background
|
Color foreground2 = [11,22,33]
|
||||||
Color cursor
|
|
||||||
|
|
||||||
foreground.red=99
|
foreground.red = 111
|
||||||
background.blue=foreground.red
|
; foreground2.red = 111
|
||||||
|
|
||||||
;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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; 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 {
|
struct Color {
|
||||||
ubyte red
|
ubyte red
|
||||||
ubyte green
|
ubyte green
|
||||||
|
Loading…
Reference in New Issue
Block a user