mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 01:49:22 +00:00
making datatype more capable (subtypes)
This commit is contained in:
parent
e80c22275d
commit
c41dc98936
@ -208,7 +208,7 @@ class StStaticVariable(name: String,
|
||||
}
|
||||
|
||||
|
||||
class StConstant(name: String, val dt: DataTypeFull, val value: Double, astNode: PtNode) :
|
||||
class StConstant(name: String, val dt: BaseDataType, val value: Double, astNode: PtNode) :
|
||||
StNode(name, StNodeType.CONSTANT, astNode)
|
||||
|
||||
|
||||
|
@ -48,7 +48,8 @@ class SymbolTableMaker(private val program: PtProgram, private val options: Comp
|
||||
StNode(node.name, StNodeType.BLOCK, node)
|
||||
}
|
||||
is PtConstant -> {
|
||||
StConstant(node.name, node.type, node.value, node)
|
||||
require(node.type.isNumericOrBool)
|
||||
StConstant(node.name, node.type.dt, node.value, node)
|
||||
}
|
||||
is PtLabel -> {
|
||||
StNode(node.name, StNodeType.LABEL, node)
|
||||
|
@ -55,16 +55,18 @@ val BaseDataType.isPassByValue get() = !this.isIterable
|
||||
|
||||
sealed class SubType(val dt: BaseDataType) {
|
||||
companion object {
|
||||
private val types = mapOf(
|
||||
BaseDataType.UBYTE to SubUnsignedByte,
|
||||
BaseDataType.BYTE to SubSignedByte,
|
||||
BaseDataType.UWORD to SubUnsignedWord,
|
||||
BaseDataType.WORD to SubSignedWord,
|
||||
BaseDataType.FLOAT to SubFloat,
|
||||
BaseDataType.BOOL to SubBool
|
||||
)
|
||||
private val types by lazy {
|
||||
// lazy because of static initialization order
|
||||
mapOf(
|
||||
BaseDataType.UBYTE to SubUnsignedByte,
|
||||
BaseDataType.BYTE to SubSignedByte,
|
||||
BaseDataType.UWORD to SubUnsignedWord,
|
||||
BaseDataType.WORD to SubSignedWord,
|
||||
BaseDataType.FLOAT to SubFloat,
|
||||
BaseDataType.BOOL to SubBool
|
||||
)}
|
||||
fun forDt(dt: BaseDataType): SubType =
|
||||
types.getOrElse(dt) { throw IllegalArgumentException("invalid sub type") }
|
||||
types.getOrElse(dt) { throw IllegalArgumentException("invalid sub type $dt possible ${types.keys}") }
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,6 +239,8 @@ data class DataTypeFull(val dt: BaseDataType, val sub: SubType?) {
|
||||
val isLong = dt == BaseDataType.LONG
|
||||
val isStringly = dt == BaseDataType.STR || dt == BaseDataType.UWORD || (dt == BaseDataType.ARRAY && (sub?.dt == BaseDataType.UBYTE || sub?.dt == BaseDataType.BYTE))
|
||||
val isSplitWordArray = dt.isSplitWordArray
|
||||
val isSplitUnsignedWordArray = dt.isSplitWordArray && sub?.dt == BaseDataType.UWORD
|
||||
val isSplitSignedWordArray = dt.isSplitWordArray && sub?.dt == BaseDataType.WORD
|
||||
val isIterable = dt.isIterable
|
||||
val isPassByRef = dt.isPassByRef
|
||||
val isPassByValue = dt.isPassByValue
|
||||
|
@ -16,18 +16,18 @@ class AtariTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer {
|
||||
override fun memorySize(dt: DataTypeFull, numElements: Int?): Int {
|
||||
if(dt.isArray || dt.isSplitWordArray) {
|
||||
require(numElements!=null)
|
||||
return when(dt.sub) {
|
||||
SubBool, SubSignedByte, SubUnsignedByte -> numElements
|
||||
SubSignedWord, SubUnsignedWord -> numElements * 2
|
||||
SubFloat -> numElements * machine.FLOAT_MEM_SIZE
|
||||
null -> throw IllegalArgumentException("invalid sub type")
|
||||
return when(dt.sub?.dt) {
|
||||
BaseDataType.BOOL, BaseDataType.UBYTE, BaseDataType.BYTE -> numElements
|
||||
BaseDataType.UWORD, BaseDataType.WORD -> numElements * 2
|
||||
BaseDataType.FLOAT-> numElements * machine.FLOAT_MEM_SIZE
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
require(numElements==null)
|
||||
|
||||
return when {
|
||||
dt.isByteOrBool -> 1
|
||||
dt.isFloat -> machine.FLOAT_MEM_SIZE
|
||||
else -> 2
|
||||
dt.isByteOrBool -> 1 * (numElements ?: 1)
|
||||
dt.isFloat -> machine.FLOAT_MEM_SIZE * (numElements ?: 1)
|
||||
else -> 2 * (numElements ?: 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,18 +15,17 @@ class VMTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer {
|
||||
override fun memorySize(dt: DataTypeFull, numElements: Int?): Int {
|
||||
if(dt.isArray || dt.isSplitWordArray) {
|
||||
require(numElements!=null)
|
||||
return when(dt.sub) {
|
||||
SubBool, SubSignedByte, SubUnsignedByte -> numElements
|
||||
SubSignedWord, SubUnsignedWord -> numElements * 2
|
||||
SubFloat -> numElements * machine.FLOAT_MEM_SIZE
|
||||
null -> throw IllegalArgumentException("invalid sub type")
|
||||
return when(dt.sub?.dt) {
|
||||
BaseDataType.BOOL, BaseDataType.UBYTE, BaseDataType.BYTE -> numElements
|
||||
BaseDataType.UWORD, BaseDataType.WORD -> numElements * 2
|
||||
BaseDataType.FLOAT-> numElements * machine.FLOAT_MEM_SIZE
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
require(numElements==null)
|
||||
return when {
|
||||
dt.isByteOrBool -> 1
|
||||
dt.isFloat -> machine.FLOAT_MEM_SIZE
|
||||
else -> 2
|
||||
dt.isByteOrBool -> 1 * (numElements ?: 1)
|
||||
dt.isFloat -> machine.FLOAT_MEM_SIZE * (numElements ?: 1)
|
||||
else -> 2 * (numElements ?: 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,18 +7,17 @@ internal object CbmMemorySizer: IMemSizer {
|
||||
override fun memorySize(dt: DataTypeFull, numElements: Int?): Int {
|
||||
if(dt.isArray || dt.isSplitWordArray) {
|
||||
require(numElements!=null)
|
||||
return when(dt.sub) {
|
||||
SubBool, SubSignedByte, SubUnsignedByte -> numElements
|
||||
SubSignedWord, SubUnsignedWord -> numElements * 2
|
||||
SubFloat -> numElements * Mflpt5.FLOAT_MEM_SIZE
|
||||
null -> throw IllegalArgumentException("invalid sub type")
|
||||
return when(dt.sub?.dt) {
|
||||
BaseDataType.BOOL, BaseDataType.UBYTE, BaseDataType.BYTE -> numElements
|
||||
BaseDataType.UWORD, BaseDataType.WORD -> numElements * 2
|
||||
BaseDataType.FLOAT-> numElements * Mflpt5.FLOAT_MEM_SIZE
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
require(numElements==null)
|
||||
return when {
|
||||
dt.isByteOrBool -> 1
|
||||
dt.isFloat -> Mflpt5.FLOAT_MEM_SIZE
|
||||
else -> 2
|
||||
dt.isByteOrBool -> 1 * (numElements ?: 1)
|
||||
dt.isFloat -> Mflpt5.FLOAT_MEM_SIZE * (numElements ?: 1)
|
||||
else -> 2 * (numElements ?: 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -738,7 +738,7 @@ internal class ProgramAndVarsGen(
|
||||
asmgen.out(" ${it.name} = ${it.address.toHex()}")
|
||||
}
|
||||
consts.sortedBy { it.name }.forEach {
|
||||
if(it.dt.isFloat)
|
||||
if(it.dt==BaseDataType.FLOAT)
|
||||
asmgen.out(" ${it.name} = ${it.value}")
|
||||
else
|
||||
asmgen.out(" ${it.name} = ${it.value.toHex()}")
|
||||
|
@ -14,11 +14,10 @@ internal object DummyMemsizer : IMemSizer {
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
require(numElements==null)
|
||||
return when {
|
||||
dt.isByteOrBool -> 1
|
||||
dt.isFloat -> 5
|
||||
else -> 2
|
||||
dt.isByteOrBool -> 1 * (numElements ?: 1)
|
||||
dt.isFloat -> 5 * (numElements ?: 1)
|
||||
else -> 2 * (numElements ?: 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,11 +12,10 @@ internal object DummyMemsizer : IMemSizer {
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
require(numElements==null)
|
||||
return when {
|
||||
dt.isByteOrBool -> 1
|
||||
dt.isFloat -> 5
|
||||
else -> 2
|
||||
dt.isByteOrBool -> 1 * (numElements ?: 1)
|
||||
dt.isFloat -> 5 * (numElements ?: 1)
|
||||
else -> 2 * (numElements ?: 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,12 +132,12 @@ internal class AstChecker(private val program: Program,
|
||||
val valueDt = returnStmt.value!!.inferType(program)
|
||||
if(valueDt.isKnown) {
|
||||
if (expectedReturnValues[0] != valueDt.getOrUndef()) {
|
||||
if(valueDt istype DataType.BOOL && expectedReturnValues[0] == DataType.UBYTE) {
|
||||
if(valueDt.isBool && expectedReturnValues[0].isUnsignedByte) {
|
||||
// if the return value is a bool and the return type is ubyte, allow this. But give a warning.
|
||||
errors.info("return type of the subroutine should probably be bool instead of ubyte", returnStmt.position)
|
||||
} else if(valueDt.isIterable && expectedReturnValues[0].isUnsignedWord) {
|
||||
// you can return a string or array when an uword (pointer) is returned
|
||||
} else if(valueDt istype DataType.UWORD && expectedReturnValues[0].isString) {
|
||||
} else if(valueDt issimpletype BaseDataType.UWORD && expectedReturnValues[0].isString) {
|
||||
// you can return a uword pointer when the return type is a string
|
||||
}
|
||||
else {
|
||||
@ -188,6 +188,9 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
val iterableDt = forLoop.iterable.inferType(program).getOr(DataTypeFull.forDt(BaseDataType.BYTE))
|
||||
|
||||
if(iterableDt.isNumeric) TODO("iterable type should not be simple numeric!? "+forLoop.position) // TODO
|
||||
|
||||
if(forLoop.iterable is IFunctionCall) {
|
||||
errors.err("can not loop over function call return value", forLoop.position)
|
||||
} else if(!(iterableDt.isIterable) && forLoop.iterable !is RangeExpression) {
|
||||
@ -200,9 +203,8 @@ internal class AstChecker(private val program: Program,
|
||||
require(loopvar.datatype.isNumericOrBool)
|
||||
when (loopvar.datatype.dt) {
|
||||
BaseDataType.UBYTE -> {
|
||||
if(iterableDt!= DataType.UBYTE && iterableDt!= DataType.ARRAY_UB && iterableDt != DataType.STR)
|
||||
if(!iterableDt.isUnsignedByte && !iterableDt.isUnsignedByteArray && !iterableDt.isString) // TODO remove ubyte check?
|
||||
errors.err("ubyte loop variable can only loop over unsigned bytes or strings", forLoop.position)
|
||||
|
||||
checkUnsignedLoopDownto0(forLoop.iterable as? RangeExpression)
|
||||
}
|
||||
BaseDataType.BOOL -> {
|
||||
@ -210,21 +212,21 @@ internal class AstChecker(private val program: Program,
|
||||
errors.err("bool loop variable can only loop over boolean array", forLoop.position)
|
||||
}
|
||||
BaseDataType.UWORD -> {
|
||||
if(iterableDt!= DataType.UBYTE && iterableDt!= DataType.UWORD && iterableDt != DataType.STR &&
|
||||
iterableDt != DataType.ARRAY_UB && iterableDt != DataType.ARRAY_UW &&
|
||||
iterableDt != DataType.ARRAY_UW_SPLIT)
|
||||
if(!iterableDt.isUnsignedByte && !iterableDt.isUnsignedWord && !iterableDt.isString && // TODO remove byte and word check?
|
||||
!iterableDt.isUnsignedByteArray && !iterableDt.isUnsignedWordArray &&
|
||||
!iterableDt.isSplitWordArray)
|
||||
errors.err("uword loop variable can only loop over unsigned bytes, words or strings", forLoop.position)
|
||||
|
||||
checkUnsignedLoopDownto0(forLoop.iterable as? RangeExpression)
|
||||
}
|
||||
BaseDataType.BYTE -> {
|
||||
if(iterableDt!= DataType.BYTE && iterableDt!= DataType.ARRAY_B)
|
||||
if(!iterableDt.isSignedByte && !iterableDt.isSignedByteArray) // TODO remove byte check?
|
||||
errors.err("byte loop variable can only loop over bytes", forLoop.position)
|
||||
}
|
||||
BaseDataType.WORD -> {
|
||||
if(iterableDt!= DataType.BYTE && iterableDt!= DataType.WORD &&
|
||||
iterableDt != DataType.ARRAY_B && iterableDt!= DataType.ARRAY_W &&
|
||||
iterableDt != DataType.ARRAY_W_SPLIT)
|
||||
if(!iterableDt.isSignedByte && !iterableDt.isSignedWord && // TODO remove byte and word check?
|
||||
!iterableDt.isSignedByteArray && !iterableDt.isSignedWordArray &&
|
||||
!iterableDt.isSplitWordArray)
|
||||
errors.err("word loop variable can only loop over bytes or words", forLoop.position)
|
||||
}
|
||||
BaseDataType.FLOAT -> {
|
||||
@ -393,12 +395,11 @@ internal class AstChecker(private val program: Program,
|
||||
err("number of return registers is not the isSameAs as number of return values")
|
||||
for(param in subroutine.parameters.zip(subroutine.asmParameterRegisters)) {
|
||||
if(param.second.registerOrPair in arrayOf(RegisterOrPair.A, RegisterOrPair.X, RegisterOrPair.Y)) {
|
||||
if (param.first.type != DataType.UBYTE && param.first.type != DataType.BYTE && param.first.type != DataType.BOOL)
|
||||
if (!param.first.type.isByteOrBool)
|
||||
errors.err("parameter '${param.first.name}' should be (u)byte or bool", param.first.position)
|
||||
}
|
||||
else if(param.second.registerOrPair in arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
|
||||
if (param.first.type != DataType.UWORD && param.first.type != DataType.WORD
|
||||
&& !param.first.type.isString && !param.first.type.isArray)
|
||||
if (!param.first.type.isWord && !param.first.type.isString && !param.first.type.isArray)
|
||||
err("parameter '${param.first.name}' should be (u)word (an address) or str")
|
||||
}
|
||||
else if(param.second.statusflag!=null) {
|
||||
@ -408,12 +409,11 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
subroutine.returntypes.zip(subroutine.asmReturnvaluesRegisters).forEachIndexed { index, pair ->
|
||||
if(pair.second.registerOrPair in arrayOf(RegisterOrPair.A, RegisterOrPair.X, RegisterOrPair.Y)) {
|
||||
if (pair.first != DataType.UBYTE && pair.first != DataType.BYTE && pair.first != DataType.BOOL)
|
||||
if (!pair.first.isByteOrBool)
|
||||
err("return type #${index + 1} should be (u)byte")
|
||||
}
|
||||
else if(pair.second.registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
|
||||
if (pair.first != DataType.UWORD && pair.first != DataType.WORD
|
||||
&& pair.first != DataType.STR && pair.first !in ArrayDatatypes)
|
||||
if (!pair.first.isWord && !pair.first.isString && !pair.first.isArray)
|
||||
err("return type #${index + 1} should be (u)word/address")
|
||||
}
|
||||
else if(pair.second.statusflag!=null) {
|
||||
@ -497,7 +497,7 @@ internal class AstChecker(private val program: Program,
|
||||
if(p.name.startsWith('_'))
|
||||
errors.err("identifiers cannot start with an underscore", p.position)
|
||||
|
||||
if(p.type.isPassByRef && p.type !in listOf(DataType.STR, DataType.ARRAY_UB)) {
|
||||
if(p.type.isPassByRef && !p.type.isString && !p.type.isUnsignedByteArray) {
|
||||
errors.err("this pass-by-reference type can't be used as a parameter type. Instead, use an uword to receive the address, or access the variable from the outer scope directly.", p.position)
|
||||
}
|
||||
}
|
||||
@ -693,7 +693,7 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
// FLOATS enabled?
|
||||
if(!compilerOptions.floats && decl.datatype.oneOf(DataType.FLOAT, DataType.ARRAY_F) && decl.type!= VarDeclType.MEMORY)
|
||||
if(!compilerOptions.floats && (decl.datatype.isFloat || decl.datatype.isFloatArray) && decl.type != VarDeclType.MEMORY)
|
||||
err("floating point used, but that is not enabled via options")
|
||||
|
||||
// ARRAY without size specifier MUST have an iterable initializer value
|
||||
@ -967,7 +967,7 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
override fun visit(array: ArrayLiteral) {
|
||||
if(array.type.isKnown) {
|
||||
if (!compilerOptions.floats && array.type.oneOf(DataType.FLOAT, DataType.ARRAY_F)) {
|
||||
if (!compilerOptions.floats && (array.type issimpletype BaseDataType.FLOAT || array.type.isFloatArray)) {
|
||||
errors.err("floating point used, but that is not enabled via options", array.position)
|
||||
}
|
||||
val arrayspec = ArrayIndex.forArray(array)
|
||||
@ -977,10 +977,7 @@ internal class AstChecker(private val program: Program,
|
||||
fun isPassByReferenceElement(e: Expression): Boolean {
|
||||
if(e is IdentifierReference) {
|
||||
val decl = e.targetVarDecl(program)
|
||||
return if(decl!=null)
|
||||
decl.datatype.isPassByRef
|
||||
else
|
||||
true // is probably a symbol that needs addr-of
|
||||
return decl?.datatype?.isPassByRef ?: true // is probably a symbol that needs addr-of
|
||||
}
|
||||
return e is StringLiteral
|
||||
}
|
||||
@ -1027,7 +1024,7 @@ internal class AstChecker(private val program: Program,
|
||||
return // any error should be reported elsewhere
|
||||
|
||||
if(expr.operator=="-") {
|
||||
if (dt != DataType.BYTE && dt != DataType.WORD && dt != DataType.FLOAT) {
|
||||
if (!(dt.isSigned && dt.isNumeric)) {
|
||||
errors.err("can only take negative of a signed number type", expr.position)
|
||||
}
|
||||
}
|
||||
@ -1078,7 +1075,7 @@ internal class AstChecker(private val program: Program,
|
||||
if(divisor==0.0)
|
||||
errors.err("division by zero", expr.right.position)
|
||||
if(expr.operator=="%") {
|
||||
if ((rightDt != DataType.UBYTE && rightDt != DataType.UWORD) || (leftDt!= DataType.UBYTE && leftDt!= DataType.UWORD))
|
||||
if ((!rightDt.isUnsignedByte && !rightDt.isUnsignedWord) || (!leftDt.isUnsignedByte && !leftDt.isUnsignedWord))
|
||||
errors.err("remainder can only be used on unsigned integer operands", expr.right.position)
|
||||
}
|
||||
}
|
||||
@ -1093,9 +1090,9 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
if(leftDt !in NumericDatatypes && leftDt != DataType.STR && leftDt != DataType.BOOL)
|
||||
if(!leftDt.isNumeric && !leftDt.isString && !leftDt.isBool)
|
||||
errors.err("left operand is not numeric or str", expr.left.position)
|
||||
if(rightDt!in NumericDatatypes && rightDt != DataType.STR && rightDt != DataType.BOOL)
|
||||
if(!rightDt.isNumeric && !rightDt.isString && !rightDt.isBool)
|
||||
errors.err("right operand is not numeric or str", expr.right.position)
|
||||
if(leftDt!=rightDt) {
|
||||
if(leftDt.isString && rightDt.isInteger && expr.operator=="*") {
|
||||
@ -1123,12 +1120,12 @@ internal class AstChecker(private val program: Program,
|
||||
} else {
|
||||
if(expr.left is TypecastExpression && expr.right is NumericLiteral && !(expr.right.inferType(program) issimpletype BaseDataType.FLOAT)) {
|
||||
val origLeftDt = (expr.left as TypecastExpression).expression.inferType(program).getOrUndef()
|
||||
if(rightDt.largerSizeThan(origLeftDt) && !(expr.right as NumericLiteral).cast(origLeftDt, true).isValid)
|
||||
if(rightDt.largerSizeThan(origLeftDt) && !(expr.right as NumericLiteral).cast(origLeftDt.dt, true).isValid)
|
||||
errors.err("operands are not the same type", expr.right.position)
|
||||
}
|
||||
if(expr.right is TypecastExpression && expr.left is NumericLiteral && !(expr.left.inferType(program) issimpletype BaseDataType.FLOAT)) {
|
||||
val origRightDt = (expr.right as TypecastExpression).expression.inferType(program).getOrUndef()
|
||||
if(leftDt.largerSizeThan(origRightDt) && !(expr.left as NumericLiteral).cast(origRightDt, true).isValid)
|
||||
if(leftDt.largerSizeThan(origRightDt) && !(expr.left as NumericLiteral).cast(origRightDt.dt, true).isValid)
|
||||
errors.err("operands are not the same type", expr.right.position)
|
||||
}
|
||||
}
|
||||
@ -1157,7 +1154,7 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
|
||||
if(expr.operator in LogicalOperators) {
|
||||
if (leftDt != DataType.BOOL || rightDt != DataType.BOOL) {
|
||||
if (!leftDt.isBool || !rightDt.isBool) {
|
||||
errors.err("logical operator requires boolean operands", expr.right.position)
|
||||
}
|
||||
}
|
||||
@ -1294,7 +1291,7 @@ internal class AstChecker(private val program: Program,
|
||||
if(funcName[0] == "sort") {
|
||||
// sort is not supported on float arrays
|
||||
val idref = functionCallStatement.args.singleOrNull() as? IdentifierReference
|
||||
if(idref!=null && idref.inferType(program) istype DataType.ARRAY_F) {
|
||||
if(idref!=null && idref.inferType(program).isFloatArray) {
|
||||
errors.err("sorting a floating point array is not supported", functionCallStatement.args.first().position)
|
||||
}
|
||||
}
|
||||
@ -1409,7 +1406,7 @@ internal class AstChecker(private val program: Program,
|
||||
errors.err("indexing requires an iterable or address uword variable", arrayIndexedExpression.position)
|
||||
val indexVariable = arrayIndexedExpression.indexer.indexExpr as? IdentifierReference
|
||||
if(indexVariable!=null) {
|
||||
if(indexVariable.targetVarDecl(program)?.datatype.isSigned) {
|
||||
if(indexVariable.targetVarDecl(program)?.datatype?.isSigned==true) {
|
||||
errors.err("variable array indexing can't be performed with signed variables", indexVariable.position)
|
||||
return
|
||||
}
|
||||
@ -1476,7 +1473,7 @@ internal class AstChecker(private val program: Program,
|
||||
when {
|
||||
constvalue == null -> errors.err("choice value must be a constant", pos)
|
||||
!constvalue.type.isIntegerOrBool -> errors.err("choice value must be a byte or word", pos)
|
||||
conditionType isnot constvalue.type -> {
|
||||
!(conditionType issimpletype constvalue.type) -> {
|
||||
if(conditionType.isKnown) {
|
||||
if(conditionType.isBool) {
|
||||
if(constvalue.number!=0.0 && constvalue.number!=1.0)
|
||||
@ -1749,23 +1746,23 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
}
|
||||
val correct: Boolean
|
||||
when (type) {
|
||||
DataType.ARRAY_UB -> {
|
||||
when {
|
||||
type.isUnsignedByteArray -> {
|
||||
correct = array.all { it in 0..255 }
|
||||
}
|
||||
DataType.ARRAY_B -> {
|
||||
type.isSignedByteArray -> {
|
||||
correct = array.all { it in -128..127 }
|
||||
}
|
||||
DataType.ARRAY_UW, DataType.ARRAY_UW_SPLIT -> {
|
||||
type.isUnsignedWordArray || type.isSplitUnsignedWordArray -> {
|
||||
correct = array.all { (it in 0..65535) }
|
||||
}
|
||||
DataType.ARRAY_W, DataType.ARRAY_W_SPLIT -> {
|
||||
type.isSignedWordArray || type.isSplitSignedWordArray -> {
|
||||
correct = array.all { it in -32768..32767 }
|
||||
}
|
||||
DataType.ARRAY_BOOL -> {
|
||||
type.isBoolArray -> {
|
||||
correct = array.all { it==0 || it==1 }
|
||||
}
|
||||
DataType.ARRAY_F -> correct = true
|
||||
type.isFloatArray -> correct = true
|
||||
else -> throw FatalAstException("invalid array type $type")
|
||||
}
|
||||
if (!correct)
|
||||
@ -1788,14 +1785,14 @@ internal class AstChecker(private val program: Program,
|
||||
return false
|
||||
}
|
||||
|
||||
val result = when(targetDatatype) {
|
||||
DataType.BOOL -> sourceDatatype.isBool
|
||||
DataType.BYTE -> sourceDatatype == DataType.BYTE
|
||||
DataType.UBYTE -> sourceDatatype == DataType.UBYTE
|
||||
DataType.WORD -> sourceDatatype in setOf(DataType.BYTE, DataType.UBYTE, DataType.WORD)
|
||||
DataType.UWORD -> sourceDatatype == DataType.UBYTE || sourceDatatype == DataType.UWORD
|
||||
DataType.FLOAT -> sourceDatatype.isNumeric
|
||||
DataType.STR -> sourceDatatype.isString
|
||||
val result = when {
|
||||
targetDatatype.isBool -> sourceDatatype.isBool
|
||||
targetDatatype.isSignedByte -> sourceDatatype.isSignedByte
|
||||
targetDatatype.isUnsignedByte -> sourceDatatype.isUnsignedByte
|
||||
targetDatatype.isSignedWord -> sourceDatatype.isSignedWord || sourceDatatype.isByte
|
||||
targetDatatype.isUnsignedWord -> sourceDatatype.isUnsignedWord || sourceDatatype.isUnsignedByte
|
||||
targetDatatype.isFloat -> sourceDatatype.isNumeric
|
||||
targetDatatype.isString -> sourceDatatype.isString
|
||||
else -> {
|
||||
errors.err("cannot assign new value to variable of type $targetDatatype", position)
|
||||
false
|
||||
@ -1805,7 +1802,7 @@ internal class AstChecker(private val program: Program,
|
||||
if(result)
|
||||
return true
|
||||
|
||||
if((sourceDatatype== DataType.UWORD || sourceDatatype== DataType.WORD) && (targetDatatype== DataType.UBYTE || targetDatatype== DataType.BYTE)) {
|
||||
if(sourceDatatype.isWord && targetDatatype.isByte) {
|
||||
errors.err("cannot assign word to byte, use msb() or lsb()?", position)
|
||||
}
|
||||
else if(sourceDatatype.isIterable && targetDatatype.isByte) {
|
||||
@ -1819,10 +1816,10 @@ internal class AstChecker(private val program: Program,
|
||||
else if(targetDatatype.isUnsignedWord && sourceDatatype.isPassByRef) {
|
||||
// this is allowed: a pass-by-reference datatype into a uword (pointer value).
|
||||
}
|
||||
else if(sourceDatatype.isBool && targetDatatype!=DataType.BOOL) {
|
||||
else if(sourceDatatype.isBool && !targetDatatype.isBool) {
|
||||
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
|
||||
}
|
||||
else if(targetDatatype.isBool && sourceDatatype!=DataType.BOOL) {
|
||||
else if(targetDatatype.isBool && !sourceDatatype.isBool) {
|
||||
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
|
||||
}
|
||||
else {
|
||||
|
@ -27,7 +27,7 @@ internal class BeforeAsmTypecastCleaner(val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
if(typecast.type==sourceDt)
|
||||
if(typecast.type==sourceDt.dt)
|
||||
return listOf(IAstModification.ReplaceNode(typecast, typecast.expression, parent))
|
||||
|
||||
if(sourceDt.isPassByRef) {
|
||||
@ -101,18 +101,18 @@ internal class BeforeAsmTypecastCleaner(val program: Program,
|
||||
val arg2 = bfcs.args[1]
|
||||
val dt1 = arg1.inferType(program).getOrUndef()
|
||||
val dt2 = arg2.inferType(program).getOrUndef()
|
||||
if(dt1==DataType.BOOL && dt2==DataType.BOOL)
|
||||
if(dt1.isBool && dt2.isBool)
|
||||
return noModifications
|
||||
else if(dt1 in ByteDatatypes) {
|
||||
if(dt2 in ByteDatatypes)
|
||||
else if(dt1.isByte) {
|
||||
if(dt2.isByte)
|
||||
return noModifications
|
||||
val (replaced, cast) = arg1.typecastTo(if(dt1== DataType.UBYTE) DataType.UWORD else DataType.WORD, dt1, true)
|
||||
val (replaced, cast) = arg1.typecastTo(if(dt1.isUnsignedByte) BaseDataType.UWORD else BaseDataType.WORD, dt1, true)
|
||||
if(replaced)
|
||||
return listOf(IAstModification.ReplaceNode(arg1, cast, bfcs))
|
||||
} else {
|
||||
if(dt2.isWord)
|
||||
return noModifications
|
||||
val (replaced, cast) = arg2.typecastTo(if(dt2== DataType.UBYTE) DataType.UWORD else DataType.WORD, dt2, true)
|
||||
val (replaced, cast) = arg2.typecastTo(if(dt2.isUnsignedByte) BaseDataType.UWORD else BaseDataType.WORD, dt2, true)
|
||||
if(replaced)
|
||||
return listOf(IAstModification.ReplaceNode(arg2, cast, bfcs))
|
||||
}
|
||||
@ -125,9 +125,9 @@ internal class BeforeAsmTypecastCleaner(val program: Program,
|
||||
val shifts = expr.right.constValue(program)
|
||||
if(shifts!=null) {
|
||||
val dt = expr.left.inferType(program)
|
||||
if(dt.istype(DataType.UBYTE) && shifts.number>=8.0)
|
||||
if(dt issimpletype BaseDataType.UBYTE && shifts.number>=8.0)
|
||||
errors.warn("shift always results in 0", expr.position)
|
||||
if(dt.istype(DataType.UWORD) && shifts.number>=16.0)
|
||||
if(dt issimpletype BaseDataType.UWORD && shifts.number>=16.0)
|
||||
errors.warn("shift always results in 0", expr.position)
|
||||
if(shifts.number<=255.0 && shifts.type.isWord) {
|
||||
val byteVal = NumericLiteral(BaseDataType.UBYTE, shifts.number, shifts.position)
|
||||
|
@ -555,7 +555,8 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr
|
||||
}
|
||||
|
||||
private fun transform(srcArr: ArrayIndexedExpression): PtArrayIndexer {
|
||||
if(srcArr.arrayvar.targetVarDecl(program)!!.datatype !in ArrayDatatypes + DataType.STR)
|
||||
val dt = srcArr.arrayvar.targetVarDecl(program)!!.datatype
|
||||
if(!dt.isArray && !dt.isString)
|
||||
throw FatalAstException("array indexing can only be used on array or string variables ${srcArr.position}")
|
||||
val eltType = srcArr.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||
val array = PtArrayIndexer(eltType, srcArr.position)
|
||||
|
@ -218,7 +218,7 @@ internal class StatementReorderer(
|
||||
}
|
||||
|
||||
if(!assignment.isAugmentable) {
|
||||
if (valueType.isString && (targetType issimpletype BaseDataType.STR || targetType istype DataType.ARRAY_B || targetType istype DataType.ARRAY_UB)) {
|
||||
if (valueType.isString && (targetType issimpletype BaseDataType.STR || targetType.isByteArray)) {
|
||||
// replace string assignment by a call to stringcopy
|
||||
return copyStringValue(assignment)
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
return noModifications
|
||||
|
||||
val modifications = mutableListOf<IAstModification>()
|
||||
addTypecastOrCastedValueModification(modifications, declValue, decl.datatype, decl)
|
||||
addTypecastOrCastedValueModification(modifications, declValue, decl.datatype.dt, decl)
|
||||
return modifications
|
||||
}
|
||||
}
|
||||
@ -104,36 +104,36 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
expr))
|
||||
}
|
||||
|
||||
if(leftDt istype DataType.BYTE && rightDt.oneOf(DataType.UBYTE, DataType.UWORD)) {
|
||||
if(leftDt issimpletype BaseDataType.BYTE && (rightDt issimpletype BaseDataType.UBYTE || rightDt issimpletype BaseDataType.UWORD)) {
|
||||
// cast left to unsigned
|
||||
val cast = TypecastExpression(expr.left, rightDt.getOrUndef(), true, expr.left.position)
|
||||
val cast = TypecastExpression(expr.left, rightDt.getOrUndef().dt, true, expr.left.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.left, cast, expr))
|
||||
}
|
||||
if(leftDt istype DataType.WORD && rightDt.oneOf(DataType.UBYTE, DataType.UWORD)) {
|
||||
if(leftDt issimpletype BaseDataType.WORD && (rightDt issimpletype BaseDataType.UBYTE || rightDt issimpletype BaseDataType.UWORD)) {
|
||||
// cast left to unsigned word. Cast right to unsigned word if it is ubyte
|
||||
val mods = mutableListOf<IAstModification>()
|
||||
val cast = TypecastExpression(expr.left, DataType.UWORD, true, expr.left.position)
|
||||
val cast = TypecastExpression(expr.left, BaseDataType.UWORD, true, expr.left.position)
|
||||
mods += IAstModification.ReplaceNode(expr.left, cast, expr)
|
||||
if(rightDt istype DataType.UBYTE) {
|
||||
if(rightDt issimpletype BaseDataType.UBYTE) {
|
||||
mods += IAstModification.ReplaceNode(expr.right,
|
||||
TypecastExpression(expr.right, DataType.UWORD, true, expr.right.position),
|
||||
TypecastExpression(expr.right, BaseDataType.UWORD, true, expr.right.position),
|
||||
expr)
|
||||
}
|
||||
return mods
|
||||
}
|
||||
if(rightDt istype DataType.BYTE && leftDt.oneOf(DataType.UBYTE, DataType.UWORD)) {
|
||||
if(rightDt issimpletype BaseDataType.BYTE && (leftDt issimpletype BaseDataType.UBYTE || leftDt issimpletype BaseDataType.UWORD)) {
|
||||
// cast right to unsigned
|
||||
val cast = TypecastExpression(expr.right, leftDt.getOrUndef(), true, expr.right.position)
|
||||
val cast = TypecastExpression(expr.right, leftDt.getOrUndef().dt, true, expr.right.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, cast, expr))
|
||||
}
|
||||
if(rightDt istype DataType.WORD && leftDt.oneOf(DataType.UBYTE, DataType.UWORD)) {
|
||||
if(rightDt issimpletype BaseDataType.WORD && (leftDt issimpletype BaseDataType.UBYTE || leftDt issimpletype BaseDataType.UWORD)) {
|
||||
// cast right to unsigned word. Cast left to unsigned word if it is ubyte
|
||||
val mods = mutableListOf<IAstModification>()
|
||||
val cast = TypecastExpression(expr.right, DataType.UWORD, true, expr.right.position)
|
||||
val cast = TypecastExpression(expr.right, BaseDataType.UWORD, true, expr.right.position)
|
||||
mods += IAstModification.ReplaceNode(expr.right, cast, expr)
|
||||
if(leftDt istype DataType.UBYTE) {
|
||||
if(leftDt issimpletype BaseDataType.UBYTE) {
|
||||
mods += IAstModification.ReplaceNode(expr.left,
|
||||
TypecastExpression(expr.left, DataType.UWORD, true, expr.left.position),
|
||||
TypecastExpression(expr.left, BaseDataType.UWORD, true, expr.left.position),
|
||||
expr)
|
||||
}
|
||||
return mods
|
||||
@ -151,8 +151,8 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
} else {
|
||||
val modifications = mutableListOf<IAstModification>()
|
||||
when {
|
||||
toFix===expr.left -> addTypecastOrCastedValueModification(modifications, expr.left, commonDt, expr)
|
||||
toFix===expr.right -> addTypecastOrCastedValueModification(modifications, expr.right, commonDt, expr)
|
||||
toFix===expr.left -> addTypecastOrCastedValueModification(modifications, expr.left, commonDt.dt, expr)
|
||||
toFix===expr.right -> addTypecastOrCastedValueModification(modifications, expr.right, commonDt.dt, expr)
|
||||
else -> throw FatalAstException("confused binary expression side")
|
||||
}
|
||||
return modifications
|
||||
@ -174,15 +174,15 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
val valuetype = valueItype.getOrUndef()
|
||||
if (valuetype != targettype) {
|
||||
if (valuetype isAssignableTo targettype) {
|
||||
if(valuetype in IterableDatatypes && targettype.isUnsignedWord)
|
||||
if(valuetype.isIterable && targettype.isUnsignedWord)
|
||||
// special case, don't typecast STR/arrays to UWORD, we support those assignments "directly"
|
||||
return noModifications
|
||||
val modifications = mutableListOf<IAstModification>()
|
||||
addTypecastOrCastedValueModification(modifications, assignment.value, targettype, assignment)
|
||||
addTypecastOrCastedValueModification(modifications, assignment.value, targettype.dt, assignment)
|
||||
return modifications
|
||||
} else {
|
||||
fun castLiteral(cvalue2: NumericLiteral): List<IAstModification.ReplaceNode> {
|
||||
val cast = cvalue2.cast(targettype, true)
|
||||
val cast = cvalue2.cast(targettype.dt, true)
|
||||
return if(cast.isValid)
|
||||
listOf(IAstModification.ReplaceNode(assignment.value, cast.valueOrZero(), assignment))
|
||||
else
|
||||
@ -225,7 +225,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
val modifications = mutableListOf<IAstModification>()
|
||||
val params = when(val sub = call.target.targetStatement(program)) {
|
||||
is BuiltinFunctionPlaceholder -> BuiltinFunctions.getValue(sub.name).parameters
|
||||
is Subroutine -> sub.parameters.map { FParam(it.name, listOf(it.type).toTypedArray()) }
|
||||
is Subroutine -> sub.parameters.map { FParam(it.name, listOf(it.type.dt).toTypedArray()) }
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
@ -234,7 +234,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
val argIdt = it.second.inferType(program)
|
||||
if (argIdt.isKnown) {
|
||||
val argDt = argIdt.getOrUndef()
|
||||
if (argDt !in it.first.possibleDatatypes) {
|
||||
if (argDt.dt !in it.first.possibleDatatypes) {
|
||||
val identifier = it.second as? IdentifierReference
|
||||
val number = it.second as? NumericLiteral
|
||||
if(number!=null) {
|
||||
@ -275,7 +275,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
|
||||
override fun after(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> {
|
||||
// warn about any implicit type casts to Float, because that may not be intended
|
||||
if(typecast.implicit && typecast.type.oneOf(DataType.FLOAT, DataType.ARRAY_F)) {
|
||||
if(typecast.implicit && typecast.type==BaseDataType.FLOAT) {
|
||||
if(options.floats)
|
||||
errors.warn("integer implicitly converted to float. Suggestion: use float literals, add an explicit cast, or revert to integer arithmetic", typecast.position)
|
||||
else
|
||||
@ -289,7 +289,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
// make sure the memory address is an uword
|
||||
val modifications = mutableListOf<IAstModification>()
|
||||
val dt = memread.addressExpression.inferType(program)
|
||||
if(dt.isKnown && dt.getOr(DataType.UWORD)!=DataType.UWORD) {
|
||||
if(dt.isKnown && !dt.getOr(DataTypeFull.forDt(BaseDataType.UWORD)).isUnsignedWord) {
|
||||
val castedValue = (memread.addressExpression as? NumericLiteral)?.cast(BaseDataType.UWORD, true)?.valueOrZero()
|
||||
if(castedValue!=null)
|
||||
modifications += IAstModification.ReplaceNode(memread.addressExpression, castedValue, memread)
|
||||
@ -303,7 +303,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
// make sure the memory address is an uword
|
||||
val modifications = mutableListOf<IAstModification>()
|
||||
val dt = memwrite.addressExpression.inferType(program)
|
||||
if(dt.isKnown && dt.getOr(DataType.UWORD)!=DataType.UWORD) {
|
||||
if(dt.isKnown && !dt.getOr(DataTypeFull.forDt(BaseDataType.UWORD)).isUnsignedWord) {
|
||||
val castedValue = (memwrite.addressExpression as? NumericLiteral)?.cast(BaseDataType.UWORD, true)?.valueOrZero()
|
||||
if(castedValue!=null)
|
||||
modifications += IAstModification.ReplaceNode(memwrite.addressExpression, castedValue, memwrite)
|
||||
@ -325,12 +325,12 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
if (returnDt istype subReturnType or returnDt.isNotAssignableTo(subReturnType))
|
||||
return noModifications
|
||||
if (returnValue is NumericLiteral) {
|
||||
val cast = returnValue.cast(subReturnType, true)
|
||||
val cast = returnValue.cast(subReturnType.dt, true)
|
||||
if(cast.isValid)
|
||||
returnStmt.value = cast.valueOrZero()
|
||||
} else {
|
||||
val modifications = mutableListOf<IAstModification>()
|
||||
addTypecastOrCastedValueModification(modifications, returnValue, subReturnType, returnStmt)
|
||||
addTypecastOrCastedValueModification(modifications, returnValue, subReturnType.dt, returnStmt)
|
||||
return modifications
|
||||
}
|
||||
}
|
||||
@ -345,7 +345,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
values?.toTypedArray()?.withIndex()?.forEach { (index, value) ->
|
||||
val valueDt = value.inferType(program)
|
||||
if(valueDt!=conditionDt) {
|
||||
val castedValue = value.typecastTo(conditionDt.getOrUndef(), valueDt.getOrUndef(), true)
|
||||
val castedValue = value.typecastTo(conditionDt.getOrUndef().dt, valueDt.getOrUndef(), true)
|
||||
if(castedValue.first) {
|
||||
castedValue.second.linkParents(whenChoice)
|
||||
values[index] = castedValue.second
|
||||
@ -362,7 +362,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
val modifications = mutableListOf<IAstModification>()
|
||||
val (commonDt, toChange) = BinaryExpression.commonDatatype(fromDt, toDt, range.from, range.to)
|
||||
if(toChange!=null)
|
||||
addTypecastOrCastedValueModification(modifications, toChange, commonDt, range)
|
||||
addTypecastOrCastedValueModification(modifications, toChange, commonDt.dt, range)
|
||||
return modifications
|
||||
}
|
||||
|
||||
@ -373,12 +373,11 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
||||
parent: Node
|
||||
) {
|
||||
val sourceDt = expressionToCast.inferType(program).getOrUndef()
|
||||
if(sourceDt == requiredType)
|
||||
if(sourceDt.dt == requiredType)
|
||||
return
|
||||
if(requiredType.isBool) {
|
||||
if(requiredType == BaseDataType.BOOL)
|
||||
return
|
||||
}
|
||||
if(expressionToCast is NumericLiteral && expressionToCast.type!=DataType.FLOAT) { // refuse to automatically truncate floats
|
||||
if(expressionToCast is NumericLiteral && expressionToCast.type!=BaseDataType.FLOAT) { // refuse to automatically truncate floats
|
||||
val castedValue = expressionToCast.cast(requiredType, true)
|
||||
if (castedValue.isValid) {
|
||||
val signOriginal = sign(expressionToCast.number)
|
||||
|
@ -1,13 +1,16 @@
|
||||
package prog8tests.compiler
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.inspectors.shouldForAll
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.statements.FunctionCallStatement
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.BuiltinFunctions
|
||||
import prog8.code.core.RegisterOrPair
|
||||
import prog8.code.core.isNumeric
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8tests.helpers.compileText
|
||||
|
||||
@ -17,16 +20,16 @@ class TestBuiltinFunctions: FunSpec({
|
||||
val func = BuiltinFunctions.getValue("sgn")
|
||||
func.parameters.size shouldBe 1
|
||||
func.parameters[0].name shouldBe "value"
|
||||
func.parameters[0].possibleDatatypes shouldBe NumericDatatypes
|
||||
func.parameters[0].possibleDatatypes. shouldForAll { it.isNumeric }
|
||||
func.pure shouldBe true
|
||||
func.returnType shouldBe DataType.BYTE
|
||||
func.returnType shouldBe BaseDataType.BYTE
|
||||
|
||||
val conv = func.callConvention(listOf(DataType.UBYTE))
|
||||
val conv = func.callConvention(listOf(BaseDataType.UBYTE))
|
||||
conv.params.size shouldBe 1
|
||||
conv.params[0].dt shouldBe DataType.UBYTE
|
||||
conv.params[0].dt shouldBe BaseDataType.UBYTE
|
||||
conv.params[0].reg shouldBe RegisterOrPair.A
|
||||
conv.params[0].variable shouldBe false
|
||||
conv.returns.dt shouldBe DataType.BYTE
|
||||
conv.returns.dt shouldBe BaseDataType.BYTE
|
||||
conv.returns.floatFac1 shouldBe false
|
||||
conv.returns.reg shouldBe RegisterOrPair.A
|
||||
}
|
||||
@ -37,7 +40,7 @@ class TestBuiltinFunctions: FunSpec({
|
||||
func.pure shouldBe false
|
||||
func.returnType shouldBe null
|
||||
|
||||
val conv = func.callConvention(listOf(DataType.UWORD, DataType.UWORD))
|
||||
val conv = func.callConvention(listOf(BaseDataType.UWORD, BaseDataType.UWORD))
|
||||
conv.params.size shouldBe 2
|
||||
conv.returns.dt shouldBe null
|
||||
conv.returns.floatFac1 shouldBe false
|
||||
@ -48,18 +51,18 @@ class TestBuiltinFunctions: FunSpec({
|
||||
val func = BuiltinFunctions.getValue("poke")
|
||||
func.parameters.size shouldBe 2
|
||||
func.parameters[0].name shouldBe "address"
|
||||
func.parameters[0].possibleDatatypes shouldBe arrayOf(DataType.UWORD)
|
||||
func.parameters[0].possibleDatatypes shouldBe arrayOf(BaseDataType.UWORD)
|
||||
func.parameters[1].name shouldBe "value"
|
||||
func.parameters[1].possibleDatatypes shouldBe arrayOf(DataType.UBYTE)
|
||||
func.parameters[1].possibleDatatypes shouldBe arrayOf(BaseDataType.UBYTE)
|
||||
func.pure shouldBe false
|
||||
func.returnType shouldBe null
|
||||
|
||||
val conv = func.callConvention(listOf(DataType.UWORD, DataType.UBYTE))
|
||||
val conv = func.callConvention(listOf(BaseDataType.UWORD, BaseDataType.UBYTE))
|
||||
conv.params.size shouldBe 2
|
||||
conv.params[0].dt shouldBe DataType.UWORD
|
||||
conv.params[0].dt shouldBe BaseDataType.UWORD
|
||||
conv.params[0].reg shouldBe null
|
||||
conv.params[0].variable shouldBe true
|
||||
conv.params[1].dt shouldBe DataType.UBYTE
|
||||
conv.params[1].dt shouldBe BaseDataType.UBYTE
|
||||
conv.params[1].reg shouldBe null
|
||||
conv.params[1].variable shouldBe true
|
||||
conv.returns.dt shouldBe null
|
||||
|
@ -9,6 +9,8 @@ import prog8.ast.IFunctionCall
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.statements.VarDeclType
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataTypeFull
|
||||
import prog8.code.core.Encoding
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8tests.helpers.compileText
|
||||
@ -40,7 +42,7 @@ class TestCompilerOnCharLit: FunSpec({
|
||||
funCall.args[0] shouldBe instanceOf<NumericLiteral>()
|
||||
}
|
||||
val arg = funCall.args[0] as NumericLiteral
|
||||
arg.type shouldBe DataType.UBYTE
|
||||
arg.type shouldBe BaseDataType.UBYTE
|
||||
arg.number shouldBe platform.encodeString("\n", Encoding.PETSCII)[0].toDouble()
|
||||
}
|
||||
|
||||
@ -64,7 +66,7 @@ class TestCompilerOnCharLit: FunSpec({
|
||||
val arg = funCall.args[0] as IdentifierReference
|
||||
val decl = arg.targetVarDecl(program)!!
|
||||
decl.type shouldBe VarDeclType.VAR
|
||||
decl.datatype shouldBe DataType.UBYTE
|
||||
decl.datatype shouldBe BaseDataType.UBYTE
|
||||
|
||||
withClue("initializer value should have been moved to separate assignment"){
|
||||
decl.value shouldBe null
|
||||
@ -75,7 +77,7 @@ class TestCompilerOnCharLit: FunSpec({
|
||||
assignInitialValue.value shouldBe instanceOf<NumericLiteral>()
|
||||
}
|
||||
val initializerValue = assignInitialValue.value as NumericLiteral
|
||||
initializerValue.type shouldBe DataType.UBYTE
|
||||
initializerValue.type shouldBe BaseDataType.UBYTE
|
||||
initializerValue.number shouldBe platform.encodeString("\n", Encoding.PETSCII)[0].toDouble()
|
||||
}
|
||||
|
||||
@ -100,7 +102,7 @@ class TestCompilerOnCharLit: FunSpec({
|
||||
is IdentifierReference -> {
|
||||
val decl = arg.targetVarDecl(program)!!
|
||||
decl.type shouldBe VarDeclType.CONST
|
||||
decl.datatype shouldBe DataType.UBYTE
|
||||
decl.datatype shouldBe DataTypeFull.forDt(BaseDataType.UBYTE)
|
||||
(decl.value as NumericLiteral).number shouldBe platform.encodeString("\n", Encoding.PETSCII)[0]
|
||||
}
|
||||
is NumericLiteral -> {
|
||||
|
@ -26,7 +26,7 @@ class TestGoldenRam: FunSpec({
|
||||
test("empty golden ram allocations") {
|
||||
val errors = ErrorReporterForTests()
|
||||
val golden = GoldenRam(options, UIntRange.EMPTY)
|
||||
val result = golden.allocate("test", DataType.UBYTE, null, null, errors)
|
||||
val result = golden.allocate("test", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
result.expectError { "should not be able to allocate anything" }
|
||||
}
|
||||
|
||||
@ -34,28 +34,28 @@ class TestGoldenRam: FunSpec({
|
||||
val errors = ErrorReporterForTests()
|
||||
val golden = GoldenRam(options, 0x400u until 0x800u)
|
||||
|
||||
var result = golden.allocate("test", DataType.UBYTE, null, null, errors)
|
||||
var result = golden.allocate("test", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
var alloc = result.getOrThrow()
|
||||
alloc.size shouldBe 1
|
||||
alloc.address shouldBe 0x400u
|
||||
result = golden.allocate("test", DataType.STR, 100, null, errors)
|
||||
result = golden.allocate("test", DataTypeFull.forDt(BaseDataType.STR), 100, null, errors)
|
||||
alloc = result.getOrThrow()
|
||||
alloc.size shouldBe 100
|
||||
alloc.address shouldBe 0x401u
|
||||
|
||||
repeat(461) {
|
||||
result = golden.allocate("test", DataType.UWORD, null, null, errors)
|
||||
result = golden.allocate("test", DataTypeFull.forDt(BaseDataType.UWORD), null, null, errors)
|
||||
alloc = result.getOrThrow()
|
||||
alloc.size shouldBe 2
|
||||
}
|
||||
|
||||
result = golden.allocate("test", DataType.UWORD, null, null, errors)
|
||||
result = golden.allocate("test", DataTypeFull.forDt(BaseDataType.UWORD), null, null, errors)
|
||||
result.expectError { "just 1 more byte available" }
|
||||
result = golden.allocate("test", DataType.UBYTE, null, null, errors)
|
||||
result = golden.allocate("test", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
alloc = result.getOrThrow()
|
||||
alloc.size shouldBe 1
|
||||
alloc.address shouldBe golden.region.last
|
||||
result = golden.allocate("test", DataType.UBYTE, null, null, errors)
|
||||
result = golden.allocate("test", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
result.expectError { "nothing more available" }
|
||||
|
||||
}
|
||||
|
@ -12,9 +12,7 @@ import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.expressions.PrefixExpression
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.core.SourceCode
|
||||
import prog8.code.core.ZeropageWish
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.C64Target
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
@ -113,7 +111,7 @@ class TestMemory: FunSpec({
|
||||
}
|
||||
|
||||
fun createTestProgramForMemoryRefViaVar(address: UInt, vartype: VarDeclType): AssignTarget {
|
||||
val decl = VarDecl(vartype, VarDeclOrigin.USERCODE, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val decl = VarDecl(vartype, VarDeclOrigin.USERCODE, DataTypeFull.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val memexpr = IdentifierReference(listOf("address"), Position.DUMMY)
|
||||
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
@ -151,7 +149,7 @@ class TestMemory: FunSpec({
|
||||
}
|
||||
|
||||
test("regular variable not in mapped IO ram on C64") {
|
||||
val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.BYTE, ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataTypeFull.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, false, Position.DUMMY)
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
@ -163,7 +161,7 @@ class TestMemory: FunSpec({
|
||||
|
||||
test("memory mapped variable not in mapped IO ram on C64") {
|
||||
val address = 0x1000u
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataTypeFull.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
@ -175,7 +173,7 @@ class TestMemory: FunSpec({
|
||||
|
||||
test("memory mapped variable in mapped IO ram on C64") {
|
||||
val address = 0xd020u
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.UBYTE, ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataTypeFull.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
@ -186,7 +184,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, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataTypeFull.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), null, 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, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
@ -199,7 +197,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, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataTypeFull.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), 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, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
@ -212,7 +210,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, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataTypeFull.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), 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, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
|
@ -10,6 +10,8 @@ import prog8.ast.expressions.ArrayLiteral
|
||||
import prog8.ast.expressions.InferredTypes
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.expressions.StringLiteral
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataTypeFull
|
||||
import prog8.code.core.Encoding
|
||||
import prog8.code.core.Position
|
||||
|
||||
@ -108,9 +110,9 @@ class TestNumericLiteral: FunSpec({
|
||||
val lvTwoR = NumericLiteral(BaseDataType.UBYTE, 2.0, dummyPos)
|
||||
val lvThreeR = NumericLiteral(BaseDataType.UBYTE, 3.0, dummyPos)
|
||||
val lvFour= NumericLiteral(BaseDataType.UBYTE, 4.0, dummyPos)
|
||||
val lv1 = ArrayLiteral(InferredTypes.InferredType.known(DataType.ARRAY_UB), arrayOf(lvOne, lvTwo, lvThree), dummyPos)
|
||||
val lv2 = ArrayLiteral(InferredTypes.InferredType.known(DataType.ARRAY_UB), arrayOf(lvOneR, lvTwoR, lvThreeR), dummyPos)
|
||||
val lv3 = ArrayLiteral(InferredTypes.InferredType.known(DataType.ARRAY_UB), arrayOf(lvOneR, lvTwoR, lvFour), dummyPos)
|
||||
val lv1 = ArrayLiteral(InferredTypes.InferredType.known(DataTypeFull.arrayFor(BaseDataType.UBYTE)), arrayOf(lvOne, lvTwo, lvThree), dummyPos)
|
||||
val lv2 = ArrayLiteral(InferredTypes.InferredType.known(DataTypeFull.arrayFor(BaseDataType.UBYTE)), arrayOf(lvOneR, lvTwoR, lvThreeR), dummyPos)
|
||||
val lv3 = ArrayLiteral(InferredTypes.InferredType.known(DataTypeFull.arrayFor(BaseDataType.UBYTE)), arrayOf(lvOneR, lvTwoR, lvFour), dummyPos)
|
||||
lv1 shouldBe lv2
|
||||
lv1 shouldNotBe lv3
|
||||
}
|
||||
@ -152,34 +154,34 @@ class TestNumericLiteral: FunSpec({
|
||||
}
|
||||
|
||||
test("optimalInteger") {
|
||||
NumericLiteral.optimalInteger(10, Position.DUMMY).type shouldBe DataType.UBYTE
|
||||
NumericLiteral.optimalInteger(10, Position.DUMMY).type shouldBe BaseDataType.UBYTE
|
||||
NumericLiteral.optimalInteger(10, Position.DUMMY).number shouldBe 10.0
|
||||
NumericLiteral.optimalInteger(-10, Position.DUMMY).type shouldBe DataType.BYTE
|
||||
NumericLiteral.optimalInteger(-10, Position.DUMMY).type shouldBe BaseDataType.BYTE
|
||||
NumericLiteral.optimalInteger(-10, Position.DUMMY).number shouldBe -10.0
|
||||
NumericLiteral.optimalInteger(1000, Position.DUMMY).type shouldBe DataType.UWORD
|
||||
NumericLiteral.optimalInteger(1000, Position.DUMMY).type shouldBe BaseDataType.UWORD
|
||||
NumericLiteral.optimalInteger(-1000, Position.DUMMY).number shouldBe -1000.0
|
||||
NumericLiteral.optimalInteger(1000u, Position.DUMMY).type shouldBe DataType.UWORD
|
||||
NumericLiteral.optimalInteger(1000u, Position.DUMMY).type shouldBe BaseDataType.UWORD
|
||||
NumericLiteral.optimalInteger(1000u, Position.DUMMY).number shouldBe 1000.0
|
||||
}
|
||||
|
||||
test("optimalNumeric") {
|
||||
NumericLiteral.optimalNumeric(10, Position.DUMMY).type shouldBe DataType.UBYTE
|
||||
NumericLiteral.optimalNumeric(10, Position.DUMMY).type shouldBe BaseDataType.UBYTE
|
||||
NumericLiteral.optimalNumeric(10, Position.DUMMY).number shouldBe 10.0
|
||||
NumericLiteral.optimalNumeric(-10, Position.DUMMY).type shouldBe DataType.BYTE
|
||||
NumericLiteral.optimalNumeric(-10, Position.DUMMY).type shouldBe BaseDataType.BYTE
|
||||
NumericLiteral.optimalNumeric(-10, Position.DUMMY).number shouldBe -10.0
|
||||
NumericLiteral.optimalNumeric(1000, Position.DUMMY).type shouldBe DataType.UWORD
|
||||
NumericLiteral.optimalNumeric(1000, Position.DUMMY).type shouldBe BaseDataType.UWORD
|
||||
NumericLiteral.optimalNumeric(1000, Position.DUMMY).number shouldBe 1000.0
|
||||
NumericLiteral.optimalNumeric(-1000, Position.DUMMY).type shouldBe DataType.WORD
|
||||
NumericLiteral.optimalNumeric(-1000, Position.DUMMY).type shouldBe BaseDataType.WORD
|
||||
NumericLiteral.optimalNumeric(-1000, Position.DUMMY).number shouldBe -1000.0
|
||||
NumericLiteral.optimalNumeric(1.123, Position.DUMMY).type shouldBe DataType.FLOAT
|
||||
NumericLiteral.optimalNumeric(1.123, Position.DUMMY).type shouldBe BaseDataType.FLOAT
|
||||
NumericLiteral.optimalNumeric(1.123, Position.DUMMY).number shouldBe 1.123
|
||||
NumericLiteral.optimalNumeric(1.0, Position.DUMMY).type shouldBe DataType.UBYTE
|
||||
NumericLiteral.optimalNumeric(1.0, Position.DUMMY).type shouldBe BaseDataType.UBYTE
|
||||
NumericLiteral.optimalNumeric(1.0, Position.DUMMY).number shouldBe 1.0
|
||||
NumericLiteral.optimalNumeric(-1.0, Position.DUMMY).type shouldBe DataType.BYTE
|
||||
NumericLiteral.optimalNumeric(-1.0, Position.DUMMY).type shouldBe BaseDataType.BYTE
|
||||
NumericLiteral.optimalNumeric(-1.0, Position.DUMMY).number shouldBe -1.0
|
||||
NumericLiteral.optimalNumeric(1234.0, Position.DUMMY).type shouldBe DataType.UWORD
|
||||
NumericLiteral.optimalNumeric(1234.0, Position.DUMMY).type shouldBe BaseDataType.UWORD
|
||||
NumericLiteral.optimalNumeric(1234.0, Position.DUMMY).number shouldBe 1234.0
|
||||
NumericLiteral.optimalNumeric(-1234.0, Position.DUMMY).type shouldBe DataType.WORD
|
||||
NumericLiteral.optimalNumeric(-1234.0, Position.DUMMY).type shouldBe BaseDataType.WORD
|
||||
NumericLiteral.optimalNumeric(-1234.0, Position.DUMMY).number shouldBe -1234.0
|
||||
}
|
||||
})
|
||||
|
@ -16,6 +16,7 @@ import prog8.code.ast.PtAssignTarget
|
||||
import prog8.code.ast.PtAssignment
|
||||
import prog8.code.ast.PtFunctionCall
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataTypeFull
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.Cx16Target
|
||||
@ -93,7 +94,7 @@ other {
|
||||
|
||||
test("generated constvalue from typecast inherits proper parent linkage") {
|
||||
val number = NumericLiteral(BaseDataType.UBYTE, 11.0, Position.DUMMY)
|
||||
val tc = TypecastExpression(number, DataType.BYTE, false, Position.DUMMY)
|
||||
val tc = TypecastExpression(number, BaseDataType.BYTE, false, Position.DUMMY)
|
||||
val program = Program("test", DummyFunctions, DummyMemsizer, DummyStringEncoder)
|
||||
tc.linkParents(ParentSentinel)
|
||||
tc.parent shouldNotBe null
|
||||
@ -102,7 +103,7 @@ other {
|
||||
val constvalue = tc.constValue(program)!!
|
||||
constvalue shouldBe instanceOf<NumericLiteral>()
|
||||
constvalue.number shouldBe 11.0
|
||||
constvalue.type shouldBe DataType.BYTE
|
||||
constvalue.type shouldBe BaseDataType.BYTE
|
||||
constvalue.parent shouldBeSameInstanceAs tc.parent
|
||||
}
|
||||
|
||||
@ -117,7 +118,7 @@ other {
|
||||
val constvalue = pfx.constValue(program)!!
|
||||
constvalue shouldBe instanceOf<NumericLiteral>()
|
||||
constvalue.number shouldBe -11.0
|
||||
constvalue.type shouldBe DataType.BYTE
|
||||
constvalue.type shouldBe BaseDataType.BYTE
|
||||
constvalue.parent shouldBeSameInstanceAs pfx.parent
|
||||
}
|
||||
|
||||
@ -555,7 +556,7 @@ main {
|
||||
arrayDecl.isArray shouldBe true
|
||||
arrayDecl.arraysize?.constIndex() shouldBe 4
|
||||
val arrayValue = arrayDecl.value as ArrayLiteral
|
||||
arrayValue.type shouldBe InferredTypes.InferredType.known(DataType.ARRAY_UB)
|
||||
arrayValue.type shouldBe InferredTypes.InferredType.known(DataTypeFull.arrayFor(BaseDataType.UBYTE))
|
||||
arrayValue.value shouldBe listOf(
|
||||
NumericLiteral.optimalInteger(1, Position.DUMMY),
|
||||
NumericLiteral.optimalInteger(3, Position.DUMMY),
|
||||
@ -927,13 +928,13 @@ main {
|
||||
funcarg2 shouldBe NumericLiteral(BaseDataType.UWORD, 8.0, Position.DUMMY)
|
||||
|
||||
val answer3ValueTc = (st[15] as Assignment).value as TypecastExpression
|
||||
answer3ValueTc.type shouldBe DataType.UWORD
|
||||
answer3ValueTc.type shouldBe BaseDataType.UWORD
|
||||
val answer3Value = answer3ValueTc.expression as FunctionCallExpression
|
||||
answer3Value.target.nameInSource shouldBe listOf("msb")
|
||||
answer3Value.args.single() shouldBe instanceOf<BinaryExpression>()
|
||||
|
||||
val funcarg3tc = (st[16] as FunctionCallStatement).args.single() as TypecastExpression
|
||||
funcarg3tc.type shouldBe DataType.UWORD
|
||||
funcarg3tc.type shouldBe BaseDataType.UWORD
|
||||
val funcarg3 = funcarg3tc.expression as FunctionCallExpression
|
||||
funcarg3.target.nameInSource shouldBe listOf("msb")
|
||||
funcarg3.args.single() shouldBe instanceOf<BinaryExpression>()
|
||||
|
@ -9,6 +9,7 @@ import prog8.code.ast.PtArray
|
||||
import prog8.code.ast.PtNumber
|
||||
import prog8.code.ast.PtString
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataTypeFull
|
||||
import prog8.code.core.Encoding
|
||||
import prog8.code.core.Position
|
||||
|
||||
@ -107,11 +108,11 @@ class TestPtNumber: FunSpec({
|
||||
val lvTwoR = PtNumber(BaseDataType.UBYTE, 2.0, dummyPos)
|
||||
val lvThreeR = PtNumber(BaseDataType.UBYTE, 3.0, dummyPos)
|
||||
val lvFour= PtNumber(BaseDataType.UBYTE, 4.0, dummyPos)
|
||||
val lv1 = PtArray(DataType.ARRAY_UB, dummyPos)
|
||||
val lv1 = PtArray(DataTypeFull.arrayFor(BaseDataType.UBYTE), dummyPos)
|
||||
arrayOf(lvOne, lvTwo, lvThree).forEach { lv1.add(it) }
|
||||
val lv2 = PtArray(DataType.ARRAY_UB, dummyPos)
|
||||
val lv2 = PtArray(DataTypeFull.arrayFor(BaseDataType.UBYTE), dummyPos)
|
||||
arrayOf(lvOneR, lvTwoR, lvThreeR).forEach { lv2.add(it) }
|
||||
val lv3 = PtArray(DataType.ARRAY_UB, dummyPos)
|
||||
val lv3 = PtArray(DataTypeFull.arrayFor(BaseDataType.UBYTE), dummyPos)
|
||||
arrayOf(lvOneR, lvTwoR, lvFour).forEach { lv3.add(it) }
|
||||
lv1 shouldBe lv2
|
||||
lv1 shouldNotBe lv3
|
||||
|
@ -8,6 +8,8 @@ import io.kotest.matchers.types.instanceOf
|
||||
import prog8.ast.IFunctionCall
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataTypeFull
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.compiler.astprocessing.hasRtsInAsm
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
@ -67,12 +69,12 @@ class TestSubroutines: FunSpec({
|
||||
asmfunc.statements.isEmpty() shouldBe true
|
||||
func.isAsmSubroutine shouldBe false
|
||||
withClue("str param for subroutines should be changed into UWORD") {
|
||||
asmfunc.parameters.single().type shouldBe DataType.UWORD
|
||||
func.parameters.single().type shouldBe DataType.UWORD
|
||||
asmfunc.parameters.single().type shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
func.parameters.single().type shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
func.statements.size shouldBe 4
|
||||
val paramvar = func.statements[0] as VarDecl
|
||||
paramvar.name shouldBe "thing"
|
||||
paramvar.datatype shouldBe DataType.UWORD
|
||||
paramvar.datatype shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
}
|
||||
val assign = func.statements[2] as Assignment
|
||||
assign.target.identifier!!.nameInSource shouldBe listOf("t2")
|
||||
@ -126,8 +128,8 @@ class TestSubroutines: FunSpec({
|
||||
asmfunc.hasRtsInAsm() shouldBe true
|
||||
func.isAsmSubroutine shouldBe false
|
||||
withClue("str param should have been changed to uword") {
|
||||
asmfunc.parameters.single().type shouldBe DataType.UWORD
|
||||
func.parameters.single().type shouldBe DataType.UWORD
|
||||
asmfunc.parameters.single().type shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
func.parameters.single().type shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
}
|
||||
|
||||
func.statements.size shouldBe 5
|
||||
@ -135,7 +137,7 @@ class TestSubroutines: FunSpec({
|
||||
val paramvar = func.statements[0] as VarDecl
|
||||
paramvar.name shouldBe "thing"
|
||||
withClue("pre-asmgen should have changed str to uword type") {
|
||||
paramvar.datatype shouldBe DataType.UWORD
|
||||
paramvar.datatype shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
}
|
||||
val assign = func.statements[2] as Assignment
|
||||
assign.target.identifier!!.nameInSource shouldBe listOf("t2")
|
||||
@ -182,8 +184,8 @@ class TestSubroutines: FunSpec({
|
||||
val asmfunc = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="asmfunc"}
|
||||
val func = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="func"}
|
||||
withClue("ubyte array param should have been replaced by UWORD pointer") {
|
||||
asmfunc.parameters.single().type shouldBe DataType.UWORD
|
||||
func.parameters.single().type shouldBe DataType.UWORD
|
||||
asmfunc.parameters.single().type shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
func.parameters.single().type shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,7 @@ import io.kotest.matchers.shouldNotBe
|
||||
import io.kotest.matchers.types.shouldBeSameInstanceAs
|
||||
import prog8.code.*
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.core.SourceCode
|
||||
import prog8.code.core.ZeropageWish
|
||||
import prog8.code.core.*
|
||||
import prog8tests.helpers.DummyMemsizer
|
||||
import prog8tests.helpers.DummyStringEncoder
|
||||
|
||||
@ -39,9 +37,9 @@ class TestSymbolTable: FunSpec({
|
||||
st.lookupUnscoped("undefined") shouldBe null
|
||||
st.lookup("undefined") shouldBe null
|
||||
st.lookup("undefined.undefined") shouldBe null
|
||||
var default = st.lookupUnscopedOrElse("undefined") { StNode("default", StNodeType.LABEL, PtIdentifier("default", DataType.BYTE, Position.DUMMY)) }
|
||||
var default = st.lookupUnscopedOrElse("undefined") { StNode("default", StNodeType.LABEL, PtIdentifier("default", DataTypeFull.forDt(BaseDataType.BYTE), Position.DUMMY)) }
|
||||
default.name shouldBe "default"
|
||||
default = st.lookupUnscopedOrElse("undefined") { StNode("default", StNodeType.LABEL, PtIdentifier("default", DataType.BYTE, Position.DUMMY)) }
|
||||
default = st.lookupUnscopedOrElse("undefined") { StNode("default", StNodeType.LABEL, PtIdentifier("default", DataTypeFull.forDt(BaseDataType.BYTE), Position.DUMMY)) }
|
||||
default.name shouldBe "default"
|
||||
|
||||
val msbFunc = st.lookupUnscopedOrElse("msb") { fail("msb must be found") }
|
||||
@ -63,7 +61,7 @@ class TestSymbolTable: FunSpec({
|
||||
val v1 = sub1.lookupUnscopedOrElse("v1") { fail("v1 must be found") } as StStaticVariable
|
||||
v1.type shouldBe StNodeType.STATICVAR
|
||||
v1.name shouldBe "v1"
|
||||
v1.dt shouldBe DataType.BYTE
|
||||
v1.dt shouldBe DataTypeFull.forDt(BaseDataType.BYTE)
|
||||
|
||||
val blockc = sub1.lookupUnscopedOrElse("blockc") { fail("blockc") } as StConstant
|
||||
blockc.type shouldBe StNodeType.CONSTANT
|
||||
@ -83,14 +81,14 @@ class TestSymbolTable: FunSpec({
|
||||
}
|
||||
|
||||
test("static vars") {
|
||||
val node = PtIdentifier("dummy", DataType.UBYTE, Position.DUMMY)
|
||||
val stVar1 = StStaticVariable("initialized", DataType.UBYTE, 99.0, null, null, null, ZeropageWish.DONTCARE, node)
|
||||
val stVar2 = StStaticVariable("uninitialized", DataType.UBYTE, null, null, null, null, ZeropageWish.DONTCARE, node)
|
||||
val node = PtIdentifier("dummy", DataTypeFull.forDt(BaseDataType.UBYTE), Position.DUMMY)
|
||||
val stVar1 = StStaticVariable("initialized", DataTypeFull.forDt(BaseDataType.UBYTE), 99.0, null, null, null, ZeropageWish.DONTCARE, node)
|
||||
val stVar2 = StStaticVariable("uninitialized", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, null, null, ZeropageWish.DONTCARE, node)
|
||||
val arrayInitNonzero = listOf(StArrayElement(1.1, null, null), StArrayElement(2.2, null, null), StArrayElement(3.3, null, null))
|
||||
val arrayInitAllzero = listOf(StArrayElement(0.0, null, null), StArrayElement(0.0, null, null), StArrayElement(0.0, null, null))
|
||||
val stVar3 = StStaticVariable("initialized", DataType.ARRAY_UW, null, null, arrayInitNonzero, 3, ZeropageWish.DONTCARE, node)
|
||||
val stVar4 = StStaticVariable("initialized", DataType.ARRAY_UW, null, null, arrayInitAllzero, 3, ZeropageWish.DONTCARE, node)
|
||||
val stVar5 = StStaticVariable("uninitialized", DataType.ARRAY_UW, null, null, null, 3, ZeropageWish.DONTCARE, node)
|
||||
val stVar3 = StStaticVariable("initialized", DataTypeFull.arrayFor(BaseDataType.UWORD), null, null, arrayInitNonzero, 3, ZeropageWish.DONTCARE, node)
|
||||
val stVar4 = StStaticVariable("initialized", DataTypeFull.arrayFor(BaseDataType.UWORD), null, null, arrayInitAllzero, 3, ZeropageWish.DONTCARE, node)
|
||||
val stVar5 = StStaticVariable("uninitialized", DataTypeFull.arrayFor(BaseDataType.UWORD), null, null, null, 3, ZeropageWish.DONTCARE, node)
|
||||
|
||||
stVar1.uninitialized shouldBe false
|
||||
stVar1.length shouldBe null
|
||||
@ -111,18 +109,18 @@ private fun makeSt(): SymbolTable {
|
||||
// first build the AST
|
||||
val astProgram = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
val astBlock1 = PtBlock("block1", false, SourceCode.Generated("block1"), PtBlock.Options(), Position.DUMMY)
|
||||
val astConstant1 = PtConstant("c1", DataType.UWORD, 12345.0, Position.DUMMY)
|
||||
val astConstant2 = PtConstant("blockc", DataType.UWORD, 999.0, Position.DUMMY)
|
||||
val astConstant1 = PtConstant("c1", DataTypeFull.forDt(BaseDataType.UWORD), 12345.0, Position.DUMMY)
|
||||
val astConstant2 = PtConstant("blockc", DataTypeFull.forDt(BaseDataType.UWORD), 999.0, Position.DUMMY)
|
||||
astBlock1.add(astConstant1)
|
||||
astBlock1.add(astConstant2)
|
||||
val astSub1 = PtSub("sub1", emptyList(), null, Position.DUMMY)
|
||||
val astSub2 = PtSub("sub2", emptyList(), null, Position.DUMMY)
|
||||
val astSub1v1 = PtVariable("v1", DataType.BYTE, ZeropageWish.DONTCARE, null, null, Position.DUMMY)
|
||||
val astSub1v2 = PtVariable("v2", DataType.BYTE, ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
||||
val astSub1v3 = PtVariable("v3", DataType.FLOAT, ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
||||
val astSub1v4 = PtVariable("slab1", DataType.UWORD, ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
||||
val astSub2v1 = PtVariable("v1", DataType.BYTE, ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
||||
val astSub2v2 = PtVariable("v2", DataType.BYTE, ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
||||
val astSub1v1 = PtVariable("v1", DataTypeFull.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE, null, null, Position.DUMMY)
|
||||
val astSub1v2 = PtVariable("v2", DataTypeFull.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
||||
val astSub1v3 = PtVariable("v3", DataTypeFull.forDt(BaseDataType.FLOAT), ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
||||
val astSub1v4 = PtVariable("slab1", DataTypeFull.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
||||
val astSub2v1 = PtVariable("v1", DataTypeFull.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
||||
val astSub2v2 = PtVariable("v2", DataTypeFull.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE,null, null, Position.DUMMY)
|
||||
astSub1.add(astSub1v1)
|
||||
astSub1.add(astSub1v2)
|
||||
astSub1.add(astSub1v3)
|
||||
@ -131,7 +129,7 @@ private fun makeSt(): SymbolTable {
|
||||
astSub2.add(astSub2v2)
|
||||
astBlock1.add(astSub1)
|
||||
astBlock1.add(astSub2)
|
||||
val astBfunc = PtIdentifier("msb", DataType.UBYTE, Position.DUMMY)
|
||||
val astBfunc = PtIdentifier("msb", DataTypeFull.forDt(BaseDataType.UBYTE), Position.DUMMY)
|
||||
astBlock1.add(astBfunc)
|
||||
val astBlock2 = PtBlock("block2", false, SourceCode.Generated("block2"), PtBlock.Options(), Position.DUMMY)
|
||||
val astSub21 = PtSub("sub1", emptyList(), null, Position.DUMMY)
|
||||
@ -152,14 +150,14 @@ private fun makeSt(): SymbolTable {
|
||||
val sub12 = StNode("sub2", StNodeType.SUBROUTINE, astSub2)
|
||||
block1.add(sub11)
|
||||
block1.add(sub12)
|
||||
block1.add(StConstant("c1", DataType.UWORD, 12345.0, astConstant1))
|
||||
block1.add(StConstant("blockc", DataType.UWORD, 999.0, astConstant2))
|
||||
sub11.add(StStaticVariable("v1", DataType.BYTE, null, null, null, null, ZeropageWish.DONTCARE, astSub1v1))
|
||||
sub11.add(StStaticVariable("v2", DataType.BYTE, null, null, null, null, ZeropageWish.DONTCARE, astSub1v2))
|
||||
sub11.add(StMemVar("v3", DataType.FLOAT, 12345u, null, astSub1v3))
|
||||
block1.add(StConstant("c1", BaseDataType.UWORD, 12345.0, astConstant1))
|
||||
block1.add(StConstant("blockc", BaseDataType.UWORD, 999.0, astConstant2))
|
||||
sub11.add(StStaticVariable("v1", DataTypeFull.forDt(BaseDataType.BYTE), null, null, null, null, ZeropageWish.DONTCARE, astSub1v1))
|
||||
sub11.add(StStaticVariable("v2", DataTypeFull.forDt(BaseDataType.BYTE), null, null, null, null, ZeropageWish.DONTCARE, astSub1v2))
|
||||
sub11.add(StMemVar("v3", DataTypeFull.forDt(BaseDataType.FLOAT), 12345u, null, astSub1v3))
|
||||
sub11.add(StMemorySlab("slab1", 200u, 64u, astSub1v4))
|
||||
sub12.add(StStaticVariable("v1", DataType.BYTE, null, null, null, null, ZeropageWish.DONTCARE, astSub2v1))
|
||||
sub12.add(StStaticVariable("v2", DataType.BYTE, null, null, null, null, ZeropageWish.DONTCARE, astSub2v2))
|
||||
sub12.add(StStaticVariable("v1", DataTypeFull.forDt(BaseDataType.BYTE), null, null, null, null, ZeropageWish.DONTCARE, astSub2v1))
|
||||
sub12.add(StStaticVariable("v2", DataTypeFull.forDt(BaseDataType.BYTE), null, null, null, null, ZeropageWish.DONTCARE, astSub2v2))
|
||||
val block2 = StNode("block2", StNodeType.BLOCK, astBlock2)
|
||||
val sub21 = StNode("sub1", StNodeType.SUBROUTINE, astSub21)
|
||||
val sub22 = StNode("sub2", StNodeType.SUBROUTINE, astSub22)
|
||||
|
@ -14,6 +14,7 @@ import prog8.ast.statements.IfElse
|
||||
import prog8.code.ast.PtAsmSub
|
||||
import prog8.code.ast.PtSub
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataTypeFull
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.VMTarget
|
||||
@ -223,11 +224,11 @@ main {
|
||||
stmts.size shouldBe 4
|
||||
val assign1tc = (stmts[2] as Assignment).value as TypecastExpression
|
||||
val assign2tc = (stmts[3] as Assignment).value as TypecastExpression
|
||||
assign1tc.type shouldBe DataType.WORD
|
||||
assign2tc.type shouldBe DataType.WORD
|
||||
assign1tc.type shouldBe BaseDataType.WORD
|
||||
assign2tc.type shouldBe BaseDataType.WORD
|
||||
assign2tc.expression shouldBe instanceOf<IdentifierReference>()
|
||||
val assign1subtc = (assign1tc.expression as TypecastExpression)
|
||||
assign1subtc.type shouldBe DataType.BYTE
|
||||
assign1subtc.type shouldBe BaseDataType.BYTE
|
||||
assign1subtc.expression shouldBe instanceOf<IdentifierReference>()
|
||||
}
|
||||
|
||||
@ -801,11 +802,11 @@ main {
|
||||
val result = compileText(VMTarget(), true, src, writeAssembly = true)!!
|
||||
val main = result.codegenAst!!.allBlocks().first()
|
||||
val derp = main.children.single { it is PtSub && it.name=="main.derp"} as PtSub
|
||||
derp.returntype shouldBe DataType.UWORD
|
||||
derp.parameters.single().type shouldBe DataType.UWORD
|
||||
derp.returntype shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
derp.parameters.single().type shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
val mult3 = main.children.single { it is PtAsmSub && it.name=="main.mult3"} as PtAsmSub
|
||||
mult3.parameters.single().second.type shouldBe DataType.UWORD
|
||||
mult3.returns.single().second shouldBe DataType.UWORD
|
||||
mult3.parameters.single().second.type shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
mult3.returns.single().second shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
}
|
||||
|
||||
test("return 0 for str converted to uword") {
|
||||
|
@ -73,26 +73,26 @@ class TestC64Zeropage: FunSpec({
|
||||
compTarget = c64target, loadAddress = 999u
|
||||
))
|
||||
|
||||
var result = zp.allocate("", DataType.UBYTE, null, null, errors)
|
||||
var result = zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
result.onFailure { fail(it.toString()) }
|
||||
result = zp.allocate("", DataType.UBYTE, null, null, errors)
|
||||
result = zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
result.onFailure { fail(it.toString()) }
|
||||
result = zp.allocate("varname", DataType.UBYTE, null, null, errors)
|
||||
result = zp.allocate("varname", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
result.onFailure { fail(it.toString()) }
|
||||
shouldThrow<IllegalArgumentException> { zp.allocate("varname", DataType.UBYTE,null, null, errors) }
|
||||
result = zp.allocate("varname2", DataType.UBYTE, null, null, errors)
|
||||
shouldThrow<IllegalArgumentException> { zp.allocate("varname", DataTypeFull.forDt(BaseDataType.UBYTE),null, null, errors) }
|
||||
result = zp.allocate("varname2", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
result.onFailure { fail(it.toString()) }
|
||||
}
|
||||
|
||||
test("testZpFloatEnable") {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
var result = zp.allocate("", DataType.FLOAT, null, null, errors)
|
||||
var result = zp.allocate("", DataTypeFull.forDt(BaseDataType.FLOAT), null, null, errors)
|
||||
result.expectError { "should be allocation error due to disabled floats" }
|
||||
val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.DONTUSE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
result = zp2.allocate("", DataType.FLOAT, null, null, errors)
|
||||
result = zp2.allocate("", DataTypeFull.forDt(BaseDataType.FLOAT), null, null, errors)
|
||||
result.expectError { "should be allocation error due to disabled ZP use" }
|
||||
val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FLOATSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
zp3.allocate("", DataType.FLOAT, null, null, errors)
|
||||
zp3.allocate("", DataTypeFull.forDt(BaseDataType.FLOAT), null, null, errors)
|
||||
}
|
||||
|
||||
test("testZpModesWithFloats") {
|
||||
@ -114,7 +114,7 @@ class TestC64Zeropage: FunSpec({
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.DONTUSE, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
println(zp.free)
|
||||
zp.availableBytes() shouldBe 0
|
||||
val result = zp.allocate("", DataType.BYTE, null, null, errors)
|
||||
val result = zp.allocate("", DataTypeFull.forDt(BaseDataType.BYTE), null, null, errors)
|
||||
result.expectError { "expected error due to disabled ZP use" }
|
||||
}
|
||||
|
||||
@ -127,9 +127,9 @@ class TestC64Zeropage: FunSpec({
|
||||
zp3.availableBytes() shouldBe 96
|
||||
val zp4 = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, c64target, 999u))
|
||||
zp4.availableBytes() shouldBe 207
|
||||
zp4.allocate("test", DataType.UBYTE, null, null, errors)
|
||||
zp4.allocate("test", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
zp4.availableBytes() shouldBe 206
|
||||
zp4.allocate("test2", DataType.UBYTE, null, null, errors)
|
||||
zp4.allocate("test2", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
zp4.availableBytes() shouldBe 205
|
||||
}
|
||||
|
||||
@ -168,19 +168,19 @@ class TestC64Zeropage: FunSpec({
|
||||
zp.hasByteAvailable() shouldBe true
|
||||
zp.hasWordAvailable() shouldBe true
|
||||
|
||||
var result = zp.allocate("", DataType.FLOAT, null, null, errors)
|
||||
var result = zp.allocate("", DataTypeFull.forDt(BaseDataType.FLOAT), null, null, errors)
|
||||
result.expectError { "expect allocation error: in regular zp there aren't 5 sequential bytes free" }
|
||||
|
||||
for (i in 0 until zp.availableBytes()) {
|
||||
val alloc = zp.allocate("", DataType.UBYTE, null, null, errors)
|
||||
val alloc = zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
alloc.getOrElse { throw it }
|
||||
}
|
||||
zp.availableBytes() shouldBe 0
|
||||
zp.hasByteAvailable() shouldBe false
|
||||
zp.hasWordAvailable() shouldBe false
|
||||
result = zp.allocate("", DataType.UBYTE, null, null, errors)
|
||||
result = zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
result.expectError { "expected allocation error" }
|
||||
result = zp.allocate("", DataType.UWORD, null, null, errors)
|
||||
result = zp.allocate("", DataTypeFull.forDt(BaseDataType.UWORD), null, null, errors)
|
||||
result.expectError { "expected allocation error" }
|
||||
}
|
||||
|
||||
@ -189,47 +189,47 @@ class TestC64Zeropage: FunSpec({
|
||||
zp.availableBytes() shouldBe 207
|
||||
zp.hasByteAvailable() shouldBe true
|
||||
zp.hasWordAvailable() shouldBe true
|
||||
var result = zp.allocate("", DataType.UWORD, null, null, errors)
|
||||
var result = zp.allocate("", DataTypeFull.forDt(BaseDataType.UWORD), null, null, errors)
|
||||
val loc = result.getOrElse { throw it } .address
|
||||
loc shouldBeGreaterThan 3u
|
||||
loc shouldNotBeIn zp.free
|
||||
val num = zp.availableBytes() / 2
|
||||
|
||||
for(i in 0..num-3) {
|
||||
zp.allocate("", DataType.UWORD, null, null, errors)
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UWORD), null, null, errors)
|
||||
}
|
||||
zp.availableBytes() shouldBe 5
|
||||
|
||||
// can't allocate because no more sequential bytes, only fragmented
|
||||
result = zp.allocate("", DataType.UWORD, null, null, errors)
|
||||
result = zp.allocate("", DataTypeFull.forDt(BaseDataType.UWORD), null, null, errors)
|
||||
result.expectError { "should give allocation error" }
|
||||
|
||||
for(i in 0..4) {
|
||||
zp.allocate("", DataType.UBYTE, null, null, errors)
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
}
|
||||
|
||||
zp.availableBytes() shouldBe 0
|
||||
zp.hasByteAvailable() shouldBe false
|
||||
zp.hasWordAvailable() shouldBe false
|
||||
result = zp.allocate("", DataType.UBYTE, null, null, errors)
|
||||
result = zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
result.expectError { "should give allocation error" }
|
||||
}
|
||||
|
||||
test("testEfficientAllocation") {
|
||||
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), CompilationOptions.AllZeropageAllowed, true, false, c64target, 999u))
|
||||
zp.availableBytes() shouldBe 17
|
||||
zp.allocate("", DataType.WORD, null, null, errors).getOrElse{throw it}.address shouldBe 0x04u
|
||||
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.address shouldBe 0x06u
|
||||
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.address shouldBe 0x0au
|
||||
zp.allocate("", DataType.UWORD, null, null, errors).getOrElse{throw it}.address shouldBe 0x9bu
|
||||
zp.allocate("", DataType.UWORD, null, null, errors).getOrElse{throw it}.address shouldBe 0x9eu
|
||||
zp.allocate("", DataType.UWORD, null, null, errors).getOrElse{throw it}.address shouldBe 0xb0u
|
||||
zp.allocate("", DataType.UWORD, null, null, errors).getOrElse{throw it}.address shouldBe 0xbeu
|
||||
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.address shouldBe 0x0eu
|
||||
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.address shouldBe 0x92u
|
||||
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.address shouldBe 0x96u
|
||||
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.address shouldBe 0xa6u
|
||||
zp.allocate("", DataType.UBYTE, null, null, errors).getOrElse{throw it}.address shouldBe 0xf9u
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.WORD), null, null, errors).getOrElse{throw it}.address shouldBe 0x04u
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors).getOrElse{throw it}.address shouldBe 0x06u
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors).getOrElse{throw it}.address shouldBe 0x0au
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UWORD), null, null, errors).getOrElse{throw it}.address shouldBe 0x9bu
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UWORD), null, null, errors).getOrElse{throw it}.address shouldBe 0x9eu
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UWORD), null, null, errors).getOrElse{throw it}.address shouldBe 0xb0u
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UWORD), null, null, errors).getOrElse{throw it}.address shouldBe 0xbeu
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors).getOrElse{throw it}.address shouldBe 0x0eu
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors).getOrElse{throw it}.address shouldBe 0x92u
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors).getOrElse{throw it}.address shouldBe 0x96u
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors).getOrElse{throw it}.address shouldBe 0xa6u
|
||||
zp.allocate("", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors).getOrElse{throw it}.address shouldBe 0xf9u
|
||||
zp.availableBytes() shouldBe 0
|
||||
}
|
||||
|
||||
@ -260,9 +260,9 @@ class TestCx16Zeropage: FunSpec({
|
||||
zp2.availableBytes() shouldBe 175
|
||||
val zp3 = CX16Zeropage(CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), CompilationOptions.AllZeropageAllowed, false, false, cx16target, 999u))
|
||||
zp3.availableBytes() shouldBe 216
|
||||
zp3.allocate("test", DataType.UBYTE, null, null, errors)
|
||||
zp3.allocate("test", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
zp3.availableBytes() shouldBe 215
|
||||
zp3.allocate("test2", DataType.UBYTE, null, null, errors)
|
||||
zp3.allocate("test2", DataTypeFull.forDt(BaseDataType.UBYTE), null, null, errors)
|
||||
zp3.availableBytes() shouldBe 214
|
||||
}
|
||||
|
||||
|
@ -209,13 +209,13 @@ class TestConst: FunSpec({
|
||||
declX2.value shouldBe null
|
||||
declY1.value shouldBe null
|
||||
declY2.value shouldBe null
|
||||
(initX1.value as NumericLiteral).type shouldBe DataType.BYTE
|
||||
(initX1.value as NumericLiteral).type shouldBe BaseDataType.BYTE
|
||||
(initX1.value as NumericLiteral).number shouldBe 11.0
|
||||
(initX2.value as NumericLiteral).type shouldBe DataType.BYTE
|
||||
(initX2.value as NumericLiteral).type shouldBe BaseDataType.BYTE
|
||||
(initX2.value as NumericLiteral).number shouldBe 11.0
|
||||
(initY1.value as NumericLiteral).type shouldBe DataType.UBYTE
|
||||
(initY1.value as NumericLiteral).type shouldBe BaseDataType.UBYTE
|
||||
(initY1.value as NumericLiteral).number shouldBe 11.0
|
||||
(initY2.value as NumericLiteral).type shouldBe DataType.UBYTE
|
||||
(initY2.value as NumericLiteral).type shouldBe BaseDataType.UBYTE
|
||||
(initY2.value as NumericLiteral).number shouldBe 11.0
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,8 @@ import io.kotest.matchers.ints.shouldBeGreaterThan
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.types.instanceOf
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataTypeFull
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.compiler.astprocessing.IntermediateAstMaker
|
||||
@ -53,15 +55,15 @@ class TestIntermediateAst: FunSpec({
|
||||
val ccdecl = entry.children[0] as PtVariable
|
||||
ccdecl.name shouldBe "cc"
|
||||
ccdecl.scopedName shouldBe "main.start.cc"
|
||||
ccdecl.type shouldBe DataType.BOOL
|
||||
ccdecl.type shouldBe DataTypeFull.forDt(BaseDataType.BOOL)
|
||||
val dddecl = entry.children[1] as PtVariable
|
||||
dddecl.name shouldBe "dd"
|
||||
dddecl.scopedName shouldBe "main.start.dd"
|
||||
dddecl.type shouldBe DataType.UBYTE
|
||||
dddecl.type shouldBe DataTypeFull.forDt(BaseDataType.UBYTE)
|
||||
|
||||
val arraydecl = entry.children[2] as IPtVariable
|
||||
arraydecl.name shouldBe "array"
|
||||
arraydecl.type shouldBe DataType.ARRAY_UB
|
||||
arraydecl.type shouldBe DataTypeFull.arrayFor(BaseDataType.UBYTE)
|
||||
|
||||
val ccAssignV = (entry.children[5] as PtAssignment).value
|
||||
ccAssignV shouldBe instanceOf<PtContainmentCheck>()
|
||||
@ -70,28 +72,28 @@ class TestIntermediateAst: FunSpec({
|
||||
}
|
||||
|
||||
test("isSame on binaryExpressions") {
|
||||
val expr1 = PtBinaryExpression("/", DataType.UBYTE, Position.DUMMY)
|
||||
val expr1 = PtBinaryExpression("/", DataTypeFull.forDt(BaseDataType.UBYTE), Position.DUMMY)
|
||||
expr1.add(PtNumber(BaseDataType.UBYTE, 1.0, Position.DUMMY))
|
||||
expr1.add(PtNumber(BaseDataType.UBYTE, 2.0, Position.DUMMY))
|
||||
val expr2 = PtBinaryExpression("/", DataType.UBYTE, Position.DUMMY)
|
||||
val expr2 = PtBinaryExpression("/", DataTypeFull.forDt(BaseDataType.UBYTE), Position.DUMMY)
|
||||
expr2.add(PtNumber(BaseDataType.UBYTE, 1.0, Position.DUMMY))
|
||||
expr2.add(PtNumber(BaseDataType.UBYTE, 2.0, Position.DUMMY))
|
||||
(expr1 isSameAs expr2) shouldBe true
|
||||
val expr3 = PtBinaryExpression("/", DataType.UBYTE, Position.DUMMY)
|
||||
val expr3 = PtBinaryExpression("/", DataTypeFull.forDt(BaseDataType.UBYTE), Position.DUMMY)
|
||||
expr3.add(PtNumber(BaseDataType.UBYTE, 2.0, Position.DUMMY))
|
||||
expr3.add(PtNumber(BaseDataType.UBYTE, 1.0, Position.DUMMY))
|
||||
(expr1 isSameAs expr3) shouldBe false
|
||||
}
|
||||
|
||||
test("isSame on binaryExpressions with associative operators") {
|
||||
val expr1 = PtBinaryExpression("+", DataType.UBYTE, Position.DUMMY)
|
||||
val expr1 = PtBinaryExpression("+", DataTypeFull.forDt(BaseDataType.UBYTE), Position.DUMMY)
|
||||
expr1.add(PtNumber(BaseDataType.UBYTE, 1.0, Position.DUMMY))
|
||||
expr1.add(PtNumber(BaseDataType.UBYTE, 2.0, Position.DUMMY))
|
||||
val expr2 = PtBinaryExpression("+", DataType.UBYTE, Position.DUMMY)
|
||||
val expr2 = PtBinaryExpression("+", DataTypeFull.forDt(BaseDataType.UBYTE), Position.DUMMY)
|
||||
expr2.add(PtNumber(BaseDataType.UBYTE, 1.0, Position.DUMMY))
|
||||
expr2.add(PtNumber(BaseDataType.UBYTE, 2.0, Position.DUMMY))
|
||||
(expr1 isSameAs expr2) shouldBe true
|
||||
val expr3 = PtBinaryExpression("+", DataType.UBYTE, Position.DUMMY)
|
||||
val expr3 = PtBinaryExpression("+", DataTypeFull.forDt(BaseDataType.UBYTE), Position.DUMMY)
|
||||
expr3.add(PtNumber(BaseDataType.UBYTE, 2.0, Position.DUMMY))
|
||||
expr3.add(PtNumber(BaseDataType.UBYTE, 1.0, Position.DUMMY))
|
||||
(expr1 isSameAs expr3) shouldBe true
|
||||
|
@ -8,6 +8,8 @@ import prog8.ast.statements.Block
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.code.ast.PtAssignTarget
|
||||
import prog8.code.ast.PtAssignment
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataTypeFull
|
||||
import prog8.code.core.SourceCode
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8.code.target.VMTarget
|
||||
@ -36,10 +38,10 @@ class TestSubroutines: FunSpec({
|
||||
val asmfunc = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="asmfunc"}
|
||||
val func = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="func"}
|
||||
asmfunc.isAsmSubroutine shouldBe true
|
||||
asmfunc.parameters.single().type shouldBe DataType.STR
|
||||
asmfunc.parameters.single().type shouldBe DataTypeFull.forDt(BaseDataType.STR)
|
||||
asmfunc.statements.isEmpty() shouldBe true
|
||||
func.isAsmSubroutine shouldBe false
|
||||
func.parameters.single().type shouldBe DataType.STR
|
||||
func.parameters.single().type shouldBe DataTypeFull.forDt(BaseDataType.STR)
|
||||
func.statements.isEmpty() shouldBe true
|
||||
}
|
||||
|
||||
@ -61,10 +63,10 @@ class TestSubroutines: FunSpec({
|
||||
val asmfunc = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="asmfunc"}
|
||||
val func = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="func"}
|
||||
asmfunc.isAsmSubroutine shouldBe true
|
||||
asmfunc.parameters.single().type shouldBe DataType.ARRAY_UB
|
||||
asmfunc.parameters.single().type shouldBe DataTypeFull.arrayFor(BaseDataType.UBYTE)
|
||||
asmfunc.statements.isEmpty() shouldBe true
|
||||
func.isAsmSubroutine shouldBe false
|
||||
func.parameters.single().type shouldBe DataType.ARRAY_UB
|
||||
func.parameters.single().type shouldBe DataTypeFull.arrayFor(BaseDataType.UBYTE)
|
||||
func.statements.isEmpty() shouldBe true
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,8 @@ import io.kotest.matchers.types.instanceOf
|
||||
import prog8.ast.IFunctionCall
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataTypeFull
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.Cx16Target
|
||||
@ -185,10 +187,10 @@ main {
|
||||
val assign2expr = (stmts[5] as Assignment).value as BinaryExpression
|
||||
assign1expr.operator shouldBe "<<"
|
||||
val leftval1 = assign1expr.left.constValue(result.compilerAst)!!
|
||||
leftval1.type shouldBe DataType.UWORD
|
||||
leftval1.type shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
leftval1.number shouldBe 1.0
|
||||
val leftval2 = assign2expr.left.constValue(result.compilerAst)!!
|
||||
leftval2.type shouldBe DataType.UWORD
|
||||
leftval2.type shouldBe DataTypeFull.forDt(BaseDataType.UWORD)
|
||||
leftval2.number shouldBe 1.0
|
||||
}
|
||||
|
||||
@ -541,12 +543,12 @@ main {
|
||||
val st = result.compilerAst.entrypoint.statements
|
||||
st.size shouldBe 8
|
||||
val assignUbb = ((st[5] as Assignment).value as TypecastExpression)
|
||||
assignUbb.type shouldBe DataType.UBYTE
|
||||
assignUbb.type shouldBe DataTypeFull.forDt(BaseDataType.UBYTE)
|
||||
assignUbb.expression shouldBe instanceOf<IdentifierReference>()
|
||||
val assignVaddr = (st[7] as Assignment).value as FunctionCallExpression
|
||||
assignVaddr.target.nameInSource shouldBe listOf("mkword")
|
||||
val tc = assignVaddr.args[0] as TypecastExpression
|
||||
tc.type shouldBe DataType.UBYTE
|
||||
tc.type shouldBe BaseDataType.UBYTE
|
||||
tc.expression shouldBe instanceOf<ArrayIndexedExpression>()
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,8 @@ class TestAsmGenSymbols: StringSpec({
|
||||
}
|
||||
|
||||
*/
|
||||
val varInSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.UWORD, ZeropageWish.DONTCARE, null, "localvar", emptyList(), NumericLiteral.optimalInteger(1234, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val var2InSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.UWORD, ZeropageWish.DONTCARE, null, "tgt", emptyList(), null, false, false, Position.DUMMY)
|
||||
val varInSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataTypeFull.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "localvar", emptyList(), NumericLiteral.optimalInteger(1234, Position.DUMMY), false, false, Position.DUMMY)
|
||||
val var2InSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataTypeFull.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "tgt", emptyList(), null, false, false, Position.DUMMY)
|
||||
val labelInSub = Label("locallabel", Position.DUMMY)
|
||||
|
||||
val tgt = AssignTarget(IdentifierReference(listOf("tgt"), Position.DUMMY), null, null, null, false, Position.DUMMY)
|
||||
@ -63,7 +63,7 @@ class TestAsmGenSymbols: StringSpec({
|
||||
val statements = mutableListOf(varInSub, var2InSub, labelInSub, assign1, assign2, assign3, assign4, assign5, assign6, assign7, assign8)
|
||||
val subroutine = Subroutine("start", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, statements, Position.DUMMY)
|
||||
val labelInBlock = Label("label_outside", Position.DUMMY)
|
||||
val varInBlock = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.UWORD, ZeropageWish.DONTCARE, null, "var_outside", emptyList(),null, false, false, Position.DUMMY)
|
||||
val varInBlock = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataTypeFull.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "var_outside", emptyList(),null, false, false, Position.DUMMY)
|
||||
val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY)
|
||||
|
||||
val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test"))
|
||||
@ -149,8 +149,8 @@ main {
|
||||
asmgen.asmSymbolName("prog8_lib.P8ZP_SCRATCH_W2") shouldBe "P8ZP_SCRATCH_W2"
|
||||
asmgen.asmSymbolName(listOf("prog8_lib","P8ZP_SCRATCH_REG")) shouldBe "P8ZP_SCRATCH_REG"
|
||||
asmgen.asmSymbolName(listOf("prog8_lib","P8ZP_SCRATCH_W2")) shouldBe "P8ZP_SCRATCH_W2"
|
||||
val id1 = PtIdentifier("prog8_lib.P8ZP_SCRATCH_REG", DataType.UBYTE, Position.DUMMY)
|
||||
val id2 = PtIdentifier("prog8_lib.P8ZP_SCRATCH_W2", DataType.UWORD, Position.DUMMY)
|
||||
val id1 = PtIdentifier("prog8_lib.P8ZP_SCRATCH_REG", DataTypeFull.forDt(BaseDataType.UBYTE), Position.DUMMY)
|
||||
val id2 = PtIdentifier("prog8_lib.P8ZP_SCRATCH_W2", DataTypeFull.forDt(BaseDataType.UWORD), Position.DUMMY)
|
||||
id1.parent = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
id2.parent = PtProgram("test", DummyMemsizer, DummyStringEncoder)
|
||||
asmgen.asmSymbolName(id1) shouldBe "P8ZP_SCRATCH_REG"
|
||||
|
@ -10,6 +10,8 @@ import io.kotest.matchers.types.instanceOf
|
||||
import prog8.code.ast.PtAssignment
|
||||
import prog8.code.ast.PtBinaryExpression
|
||||
import prog8.code.ast.PtVariable
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataTypeFull
|
||||
import prog8.code.target.*
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
import prog8tests.helpers.compileText
|
||||
@ -73,7 +75,7 @@ main {
|
||||
val seed = start.children[0] as PtVariable
|
||||
seed.name shouldBe "p8v_seed"
|
||||
seed.value shouldBe null
|
||||
seed.type shouldBe DataType.ARRAY_UW
|
||||
seed.type shouldBe DataTypeFull.arrayFor(BaseDataType.UWORD)
|
||||
val assign = start.children[1] as PtAssignment
|
||||
assign.target.identifier!!.name shouldBe "cx16.r0"
|
||||
assign.value shouldBe instanceOf<PtBinaryExpression>()
|
||||
|
@ -24,20 +24,23 @@ internal object DummyMemsizer : IMemSizer {
|
||||
override fun memorySize(dt: DataTypeFull, numElements: Int?): Int {
|
||||
if(dt.isArray || dt.isSplitWordArray) {
|
||||
require(numElements!=null)
|
||||
return when(dt.sub) {
|
||||
SubBool, SubSignedByte, SubUnsignedByte -> numElements
|
||||
SubSignedWord, SubUnsignedWord -> numElements*2
|
||||
SubFloat -> numElements*5
|
||||
null -> throw IllegalArgumentException("invalid sub type")
|
||||
return when(dt.sub?.dt) {
|
||||
BaseDataType.BOOL, BaseDataType.BYTE, BaseDataType.UBYTE -> numElements
|
||||
BaseDataType.UWORD, BaseDataType.WORD -> numElements*2
|
||||
BaseDataType.FLOAT -> numElements*5
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
require(numElements==null)
|
||||
return when {
|
||||
dt.isByteOrBool -> 1
|
||||
dt.isFloat -> 5
|
||||
else -> 2
|
||||
dt.isByteOrBool -> 1 * (numElements ?: 1)
|
||||
dt.isFloat -> 5 * (numElements ?: 1)
|
||||
else -> 2 * (numElements ?: 1)
|
||||
}
|
||||
}
|
||||
|
||||
override fun memorySize(dt: SubType): Int {
|
||||
return memorySize(DataTypeFull.forDt(dt.dt), null)
|
||||
}
|
||||
}
|
||||
|
||||
internal object DummyStringEncoder : IStringEncoding {
|
||||
@ -78,4 +81,8 @@ internal object DummyCompilationTarget : ICompilationTarget {
|
||||
override fun memorySize(dt: DataTypeFull, numElements: Int?): Int {
|
||||
throw NotImplementedError("dummy")
|
||||
}
|
||||
|
||||
override fun memorySize(dt: SubType): Int {
|
||||
throw NotImplementedError("dummy")
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ object InferredTypes {
|
||||
if(isUnknown || isVoid) transform(this) else datatype!!
|
||||
infix fun istype(type: DataTypeFull): Boolean = if(isUnknown || isVoid) false else this.datatype==type // strict equality if known
|
||||
infix fun issimpletype(type: BaseDataType): Boolean = if(isUnknown || isVoid) false else (this.datatype?.dt==type && this.datatype?.sub==null) // strict equality if known
|
||||
fun oneOf(vararg types: DataTypeFull) = if(isUnknown || isVoid) false else this.datatype in types
|
||||
|
||||
companion object {
|
||||
fun unknown() = InferredType(isUnknown = true, isVoid = false, datatype = null)
|
||||
@ -56,6 +55,8 @@ object InferredTypes {
|
||||
val isNumeric get() = datatype?.isNumeric==true
|
||||
val isNumericOrBool get() = datatype?.isNumericOrBool==true
|
||||
val isArray get() = datatype?.isArray==true
|
||||
val isFloatArray get() = datatype?.isFloatArray==true
|
||||
val isByteArray get() = datatype?.isByteArray==true
|
||||
val isString get() = datatype?.isString==true
|
||||
val isStringLy get() = datatype?.isStringly==true
|
||||
val isIterable get() = datatype?.isIterable==true
|
||||
|
@ -1,7 +1,7 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
is the second MemorySize() required?
|
||||
add extra Memsizer unit tests
|
||||
|
||||
replace some when { xxx.isWord... } with (when xxx.dt) { UWORD -> ...} again
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user