get rid of vardecl.declareddatatype

This commit is contained in:
Irmen de Jong 2023-12-26 19:27:50 +01:00
parent ffdc658dc8
commit 0a4de45453
9 changed files with 44 additions and 89 deletions

View File

@ -161,7 +161,7 @@ val ElementToArrayTypes = mapOf(
DataType.UWORD to DataType.ARRAY_UW, DataType.UWORD to DataType.ARRAY_UW,
DataType.FLOAT to DataType.ARRAY_F, DataType.FLOAT to DataType.ARRAY_F,
DataType.BOOL to DataType.ARRAY_BOOL, DataType.BOOL to DataType.ARRAY_BOOL,
DataType.STR to DataType.UWORD // array of str is just an array of pointers DataType.STR to DataType.ARRAY_UW // array of str is just an array of pointers
) )
val Cx16VirtualRegisters = arrayOf( val Cx16VirtualRegisters = arrayOf(

View File

@ -45,8 +45,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
} }
override fun visit(decl: VarDecl) { override fun visit(decl: VarDecl) {
decl.datatypeErrors.forEach { errors.err(it.message, it.position) }
if(decl.name in BuiltinFunctions) if(decl.name in BuiltinFunctions)
errors.err("builtin function cannot be redefined", decl.position) errors.err("builtin function cannot be redefined", decl.position)

View File

@ -195,9 +195,8 @@ class AstPreprocessor(val program: Program,
} }
private fun makeSplitArray(decl: VarDecl): Iterable<IAstModification> { private fun makeSplitArray(decl: VarDecl): Iterable<IAstModification> {
val splitDt = ArrayToElementTypes.getValue(decl.datatype)
val newDecl = VarDecl( val newDecl = VarDecl(
decl.type, decl.origin, splitDt, decl.zeropage, decl.arraysize, decl.name, emptyList(), decl.type, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, emptyList(),
decl.value, true, decl.sharedWithAsm, true, decl.position decl.value, true, decl.sharedWithAsm, true, decl.position
) )
return listOf(IAstModification.ReplaceNode(decl, newDecl, decl.parent)) return listOf(IAstModification.ReplaceNode(decl, newDecl, decl.parent))

View File

@ -29,8 +29,8 @@ internal class BoolRemover(val program: Program) : AstWalker() {
if(newvalue.number!=0.0) if(newvalue.number!=0.0)
newvalue = NumericLiteral(DataType.UBYTE, 1.0, newvalue.position) newvalue = NumericLiteral(DataType.UBYTE, 1.0, newvalue.position)
} }
val ubyteDecl = VarDecl(decl.type, decl.origin, DataType.UBYTE, decl.zeropage, decl.arraysize, decl.name, emptyList(), val ubyteDecl = VarDecl(decl.type, decl.origin, DataType.UBYTE, decl.zeropage, null, decl.name, emptyList(),
newvalue, decl.isArray, decl.sharedWithAsm, decl.splitArray, decl.position) newvalue, false, decl.sharedWithAsm, false, decl.position)
return listOf(IAstModification.ReplaceNode(decl, ubyteDecl, parent)) return listOf(IAstModification.ReplaceNode(decl, ubyteDecl, parent))
} }

View File

@ -185,7 +185,7 @@ class TestMemory: FunSpec({
} }
test("array not in mapped IO ram") { test("array not in mapped IO ram") {
val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, false, false, Position.DUMMY) val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), null, true, false, false, Position.DUMMY)
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
@ -198,7 +198,7 @@ class TestMemory: FunSpec({
test("memory mapped array not in mapped IO ram") { test("memory mapped array not in mapped IO ram") {
val address = 0x1000u val address = 0x1000u
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), true, false, false, Position.DUMMY)
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
@ -211,7 +211,7 @@ class TestMemory: FunSpec({
test("memory mapped array in mapped IO ram") { test("memory mapped array in mapped IO ram") {
val address = 0xd800u val address = 0xd800u
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, false, Position.DUMMY) val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.ARRAY_UB, ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), true, false, false, Position.DUMMY)
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY) val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
val target = AssignTarget(null, arrayindexed, null, Position.DUMMY) val target = AssignTarget(null, arrayindexed, null, Position.DUMMY)
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY) val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)

View File

@ -654,18 +654,31 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl
} }
val identifiers = identifier() val identifiers = identifier()
val name = if(identifiers.size==1) identifiers[0].NAME().text else "<multiple>" val name = if(identifiers.size==1) identifiers[0].NAME().text else "<multiple>"
val isArray = ARRAYSIG() != null || arrayindex() != null
val split = options.SPLIT().isNotEmpty()
val origDt = datatype()?.toAst() ?: DataType.UNDEFINED
val dt = if(isArray) {
val arrayDt = ElementToArrayTypes.getValue(origDt)
if(split) {
when(arrayDt) {
DataType.ARRAY_UW -> DataType.ARRAY_UW_SPLIT
DataType.ARRAY_W -> DataType.ARRAY_W_SPLIT
else -> throw SyntaxError("split can only be used on word arrays", toPosition())
}
} else arrayDt
} else origDt
return VarDecl( return VarDecl(
type, VarDeclOrigin.USERCODE, type, VarDeclOrigin.USERCODE,
datatype()?.toAst() ?: DataType.UNDEFINED, dt,
zp, zp,
arrayindex()?.toAst(), arrayindex()?.toAst(),
name, name,
if(identifiers.size==1) emptyList() else identifiers.map { it.NAME().text }, if(identifiers.size==1) emptyList() else identifiers.map { it.NAME().text },
value, value,
ARRAYSIG() != null || arrayindex() != null, isArray,
options.SHARED().isNotEmpty(), options.SHARED().isNotEmpty(),
options.SPLIT().isNotEmpty(), split,
toPosition() toPosition()
) )
} }

View File

@ -2,7 +2,6 @@ package prog8.ast.statements
import prog8.ast.* import prog8.ast.*
import prog8.ast.base.FatalAstException import prog8.ast.base.FatalAstException
import prog8.ast.base.SyntaxError
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
@ -204,7 +203,7 @@ enum class VarDeclType {
class VarDecl(val type: VarDeclType, class VarDecl(val type: VarDeclType,
val origin: VarDeclOrigin, val origin: VarDeclOrigin,
private val declaredDatatype: DataType, val datatype: DataType,
var zeropage: ZeropageWish, var zeropage: ZeropageWish,
var arraysize: ArrayIndex?, var arraysize: ArrayIndex?,
override val name: String, override val name: String,
@ -217,13 +216,19 @@ class VarDecl(val type: VarDeclType,
override lateinit var parent: Node override lateinit var parent: Node
var allowInitializeWithZero = true var allowInitializeWithZero = true
// prefix for literal values that are turned into a variable on the heap init {
if(isArray)
require(datatype in ArrayDatatypes) { "array dt mismatch" }
else
require(datatype !in ArrayDatatypes) { "array dt mismatch" }
}
companion object { companion object {
private var autoHeapValueSequenceNumber = 0 private var autoHeapValueSequenceNumber = 0
fun fromParameter(param: SubroutineParameter): VarDecl { fun fromParameter(param: SubroutineParameter): VarDecl {
return VarDecl(VarDeclType.VAR, VarDeclOrigin.SUBROUTINEPARAM, param.type, ZeropageWish.DONTCARE, null, param.name, emptyList(), null, val dt = if(param.type in ArrayDatatypes) DataType.UWORD else param.type
return VarDecl(VarDeclType.VAR, VarDeclOrigin.SUBROUTINEPARAM, dt, ZeropageWish.DONTCARE, null, param.name, emptyList(), null,
isArray = false, isArray = false,
sharedWithAsm = false, sharedWithAsm = false,
splitArray = false, splitArray = false,
@ -234,45 +239,12 @@ class VarDecl(val type: VarDeclType,
fun createAuto(array: ArrayLiteral, splitArray: Boolean): VarDecl { fun createAuto(array: ArrayLiteral, splitArray: Boolean): VarDecl {
val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}" val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}"
val arrayDt = array.type.getOrElse { throw FatalAstException("unknown dt") } val arrayDt = array.type.getOrElse { throw FatalAstException("unknown dt") }
val declaredType = ArrayToElementTypes.getValue(arrayDt)
val arraysize = ArrayIndex.forArray(array) val arraysize = ArrayIndex.forArray(array)
return VarDecl(VarDeclType.VAR, VarDeclOrigin.ARRAYLITERAL, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, emptyList(), array, return VarDecl(VarDeclType.VAR, VarDeclOrigin.ARRAYLITERAL, arrayDt, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, emptyList(), array,
isArray = true, sharedWithAsm = false, splitArray = splitArray, position = array.position) isArray = true, sharedWithAsm = false, splitArray = splitArray, position = array.position)
} }
} }
val datatypeErrors = mutableListOf<SyntaxError>() // don't crash at init time, report them in the AstChecker
val datatype: DataType
init {
val dt =
if (!isArray) declaredDatatype
else when (declaredDatatype) {
DataType.UBYTE -> DataType.ARRAY_UB
DataType.BYTE -> DataType.ARRAY_B
DataType.UWORD -> DataType.ARRAY_UW
DataType.WORD -> DataType.ARRAY_W
DataType.FLOAT -> DataType.ARRAY_F
DataType.BOOL -> DataType.ARRAY_BOOL
DataType.STR -> DataType.ARRAY_UW // use memory address of the string instead
else -> {
datatypeErrors.add(SyntaxError("array can only contain bytes/words/floats/strings(ptrs)", position))
DataType.ARRAY_UB
}
}
datatype = if(splitArray) {
when(dt) {
DataType.ARRAY_UW -> DataType.ARRAY_UW_SPLIT
DataType.ARRAY_W -> DataType.ARRAY_W_SPLIT
else -> {
datatypeErrors.add(SyntaxError("split can only be used on word arrays", position))
DataType.UNDEFINED
}
}
} else dt
}
override fun linkParents(parent: Node) { override fun linkParents(parent: Node) {
this.parent = parent this.parent = parent
arraysize?.linkParents(this) arraysize?.linkParents(this)
@ -291,8 +263,10 @@ class VarDecl(val type: VarDeclType,
"VarDecl(name=$name, vartype=$type, datatype=$datatype, value=$value, pos=$position)" "VarDecl(name=$name, vartype=$type, datatype=$datatype, value=$value, pos=$position)"
fun zeroElementValue(): NumericLiteral { fun zeroElementValue(): NumericLiteral {
if(allowInitializeWithZero) if(allowInitializeWithZero) {
return defaultZero(declaredDatatype, position) return if(isArray) defaultZero(ArrayToElementTypes.getValue(datatype), position)
else defaultZero(datatype, position)
}
else else
throw IllegalArgumentException("attempt to get zero value for vardecl that shouldn't get it") throw IllegalArgumentException("attempt to get zero value for vardecl that shouldn't get it")
} }
@ -300,7 +274,7 @@ class VarDecl(val type: VarDeclType,
override fun copy(): VarDecl { override fun copy(): VarDecl {
if(names.size>1) if(names.size>1)
throw FatalAstException("should not copy a vardecl that still has multiple names") throw FatalAstException("should not copy a vardecl that still has multiple names")
val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), name, names, value?.copy(), val copy = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), name, names, value?.copy(),
isArray, sharedWithAsm, splitArray, position) isArray, sharedWithAsm, splitArray, position)
copy.allowInitializeWithZero = this.allowInitializeWithZero copy.allowInitializeWithZero = this.allowInitializeWithZero
return copy return copy
@ -320,19 +294,19 @@ class VarDecl(val type: VarDeclType,
if(value?.isSimple==true) { if(value?.isSimple==true) {
// just copy the initialization value to a separata vardecl for each component // just copy the initialization value to a separata vardecl for each component
return names.map { return names.map {
val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), it, emptyList(), value?.copy(), val copy = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), it, emptyList(), value?.copy(),
isArray, sharedWithAsm, splitArray, position) isArray, sharedWithAsm, splitArray, position)
copy.allowInitializeWithZero = this.allowInitializeWithZero copy.allowInitializeWithZero = this.allowInitializeWithZero
copy copy
} }
} else { } else {
// evaluate the value once in the vardecl for the first component, and set the other components to the first // evaluate the value once in the vardecl for the first component, and set the other components to the first
val first = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), names[0], emptyList(), value?.copy(), val first = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), names[0], emptyList(), value?.copy(),
isArray, sharedWithAsm, splitArray, position) isArray, sharedWithAsm, splitArray, position)
first.allowInitializeWithZero = this.allowInitializeWithZero first.allowInitializeWithZero = this.allowInitializeWithZero
val firstVar = firstVarAsValue(first) val firstVar = firstVarAsValue(first)
return listOf(first) + names.drop(1 ).map { return listOf(first) + names.drop(1 ).map {
val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), it, emptyList(), firstVar.copy(), val copy = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), it, emptyList(), firstVar.copy(),
isArray, sharedWithAsm, splitArray, position) isArray, sharedWithAsm, splitArray, position)
copy.allowInitializeWithZero = this.allowInitializeWithZero copy.allowInitializeWithZero = this.allowInitializeWithZero
copy copy

View File

@ -2,9 +2,6 @@
TODO TODO
==== ====
- get rid of vardecl.declareddatatype
- get rid of memory mapped variables: treat them as syntactic sugar for a poke/peek to the symbol.
- add -nowarnunused, or %option ignore_unused (module and block scope), to suppress all warnings about unused symbols. Useful in libraries. - add -nowarnunused, or %option ignore_unused (module and block scope), to suppress all warnings about unused symbols. Useful in libraries.
put this in all library code, like %option no_symbol_prefixing, and get rid of the "trick" it uses currently to suppress unused symbol warnings for library modules. put this in all library code, like %option no_symbol_prefixing, and get rid of the "trick" it uses currently to suppress unused symbol warnings for library modules.

View File

@ -1,36 +1,10 @@
%import textio %import textio
%import floats
%zeropage basicsafe %zeropage basicsafe
main { main {
sub start() { sub start() {
uword zz str[] names = ["irmen", "de", "jong"]
word zz2 uword zz = names[1]
ubyte bb txt.print(names[1])
byte bb2
bb2 |= bb
bb2 |= zz2
; uword[20] @split foobar
; ubyte[20] @split foobar2
;
; sys.push(11)
; sys.pushw(2222)
; floats.push(floats.π)
; cx16.r2++
;
; float pi = floats.pop()
; floats.print_f(pi)
; txt.nl()
;
; cx16.r1 = sys.popw()
; cx16.r0L = sys.pop()
;
; txt.print_ub(cx16.r0L)
; txt.nl()
; txt.print_uw(cx16.r1)
; txt.nl()
} }
} }