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.FLOAT to DataType.ARRAY_F,
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(

View File

@ -45,8 +45,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
}
override fun visit(decl: VarDecl) {
decl.datatypeErrors.forEach { errors.err(it.message, it.position) }
if(decl.name in BuiltinFunctions)
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> {
val splitDt = ArrayToElementTypes.getValue(decl.datatype)
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
)
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)
newvalue = NumericLiteral(DataType.UBYTE, 1.0, newvalue.position)
}
val ubyteDecl = VarDecl(decl.type, decl.origin, DataType.UBYTE, decl.zeropage, decl.arraysize, decl.name, emptyList(),
newvalue, decl.isArray, decl.sharedWithAsm, decl.splitArray, decl.position)
val ubyteDecl = VarDecl(decl.type, decl.origin, DataType.UBYTE, decl.zeropage, null, decl.name, emptyList(),
newvalue, false, decl.sharedWithAsm, false, decl.position)
return listOf(IAstModification.ReplaceNode(decl, ubyteDecl, parent))
}

View File

@ -185,7 +185,7 @@ class TestMemory: FunSpec({
}
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 target = AssignTarget(null, arrayindexed, null, 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") {
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 target = AssignTarget(null, arrayindexed, null, 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") {
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 target = AssignTarget(null, arrayindexed, null, 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 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(
type, VarDeclOrigin.USERCODE,
datatype()?.toAst() ?: DataType.UNDEFINED,
dt,
zp,
arrayindex()?.toAst(),
name,
if(identifiers.size==1) emptyList() else identifiers.map { it.NAME().text },
value,
ARRAYSIG() != null || arrayindex() != null,
isArray,
options.SHARED().isNotEmpty(),
options.SPLIT().isNotEmpty(),
split,
toPosition()
)
}

View File

@ -2,7 +2,6 @@ package prog8.ast.statements
import prog8.ast.*
import prog8.ast.base.FatalAstException
import prog8.ast.base.SyntaxError
import prog8.ast.expressions.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstVisitor
@ -204,7 +203,7 @@ enum class VarDeclType {
class VarDecl(val type: VarDeclType,
val origin: VarDeclOrigin,
private val declaredDatatype: DataType,
val datatype: DataType,
var zeropage: ZeropageWish,
var arraysize: ArrayIndex?,
override val name: String,
@ -217,13 +216,19 @@ class VarDecl(val type: VarDeclType,
override lateinit var parent: Node
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 {
private var autoHeapValueSequenceNumber = 0
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,
sharedWithAsm = false,
splitArray = false,
@ -234,45 +239,12 @@ class VarDecl(val type: VarDeclType,
fun createAuto(array: ArrayLiteral, splitArray: Boolean): VarDecl {
val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}"
val arrayDt = array.type.getOrElse { throw FatalAstException("unknown dt") }
val declaredType = ArrayToElementTypes.getValue(arrayDt)
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)
}
}
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) {
this.parent = parent
arraysize?.linkParents(this)
@ -291,8 +263,10 @@ class VarDecl(val type: VarDeclType,
"VarDecl(name=$name, vartype=$type, datatype=$datatype, value=$value, pos=$position)"
fun zeroElementValue(): NumericLiteral {
if(allowInitializeWithZero)
return defaultZero(declaredDatatype, position)
if(allowInitializeWithZero) {
return if(isArray) defaultZero(ArrayToElementTypes.getValue(datatype), position)
else defaultZero(datatype, position)
}
else
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 {
if(names.size>1)
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)
copy.allowInitializeWithZero = this.allowInitializeWithZero
return copy
@ -320,19 +294,19 @@ class VarDecl(val type: VarDeclType,
if(value?.isSimple==true) {
// just copy the initialization value to a separata vardecl for each component
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)
copy.allowInitializeWithZero = this.allowInitializeWithZero
copy
}
} else {
// 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)
first.allowInitializeWithZero = this.allowInitializeWithZero
val firstVar = firstVarAsValue(first)
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)
copy.allowInitializeWithZero = this.allowInitializeWithZero
copy

View File

@ -2,9 +2,6 @@
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.
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 floats
%zeropage basicsafe
main {
sub start() {
uword zz
word zz2
ubyte bb
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()
str[] names = ["irmen", "de", "jong"]
uword zz = names[1]
txt.print(names[1])
}
}