From c41dc98936ac56fad41a765aaeee66636ab72534 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 4 Sep 2024 21:49:47 +0200 Subject: [PATCH] making datatype more capable (subtypes) --- codeCore/src/prog8/code/SymbolTable.kt | 2 +- codeCore/src/prog8/code/SymbolTableMaker.kt | 3 +- codeCore/src/prog8/code/core/Enumerations.kt | 22 ++-- codeCore/src/prog8/code/target/AtariTarget.kt | 18 ++-- codeCore/src/prog8/code/target/VMTarget.kt | 17 ++- .../prog8/code/target/cbm/CbmMemorySizer.kt | 17 ++- .../codegen/cpu6502/ProgramAndVarsGen.kt | 2 +- codeGenCpu6502/test/Dummies.kt | 7 +- codeGenIntermediate/test/Dummies.kt | 7 +- .../compiler/astprocessing/AstChecker.kt | 101 +++++++++--------- .../astprocessing/BeforeAsmTypecastCleaner.kt | 16 +-- .../astprocessing/IntermediateAstMaker.kt | 3 +- .../astprocessing/StatementReorderer.kt | 2 +- .../compiler/astprocessing/TypecastsAdder.kt | 61 ++++++----- compiler/test/TestBuiltinFunctions.kt | 25 +++-- compiler/test/TestCompilerOnCharLit.kt | 10 +- compiler/test/TestGoldenRam.kt | 14 +-- compiler/test/TestMemory.kt | 18 ++-- compiler/test/TestNumericLiteral.kt | 34 +++--- compiler/test/TestOptimization.kt | 13 +-- compiler/test/TestPtNumber.kt | 7 +- compiler/test/TestSubroutines.kt | 18 ++-- compiler/test/TestSymbolTable.kt | 54 +++++----- compiler/test/TestTypecasts.kt | 15 +-- compiler/test/TestZeropage.kt | 68 ++++++------ compiler/test/ast/TestConst.kt | 8 +- compiler/test/ast/TestIntermediateAst.kt | 20 ++-- compiler/test/ast/TestSubroutines.kt | 10 +- compiler/test/ast/TestVariousCompilerAst.kt | 10 +- .../test/codegeneration/TestAsmGenSymbols.kt | 10 +- .../test/codegeneration/TestVariousCodeGen.kt | 4 +- compiler/test/helpers/Dummies.kt | 25 +++-- .../prog8/ast/expressions/InferredTypes.kt | 3 +- docs/source/todo.rst | 2 +- 34 files changed, 334 insertions(+), 312 deletions(-) diff --git a/codeCore/src/prog8/code/SymbolTable.kt b/codeCore/src/prog8/code/SymbolTable.kt index 523ea0146..78561a45b 100644 --- a/codeCore/src/prog8/code/SymbolTable.kt +++ b/codeCore/src/prog8/code/SymbolTable.kt @@ -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) diff --git a/codeCore/src/prog8/code/SymbolTableMaker.kt b/codeCore/src/prog8/code/SymbolTableMaker.kt index 7379dedec..9cc818a18 100644 --- a/codeCore/src/prog8/code/SymbolTableMaker.kt +++ b/codeCore/src/prog8/code/SymbolTableMaker.kt @@ -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) diff --git a/codeCore/src/prog8/code/core/Enumerations.kt b/codeCore/src/prog8/code/core/Enumerations.kt index 4d2bf236f..16a5de3e5 100644 --- a/codeCore/src/prog8/code/core/Enumerations.kt +++ b/codeCore/src/prog8/code/core/Enumerations.kt @@ -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 diff --git a/codeCore/src/prog8/code/target/AtariTarget.kt b/codeCore/src/prog8/code/target/AtariTarget.kt index d6333c3a4..831ad7daa 100644 --- a/codeCore/src/prog8/code/target/AtariTarget.kt +++ b/codeCore/src/prog8/code/target/AtariTarget.kt @@ -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) } } diff --git a/codeCore/src/prog8/code/target/VMTarget.kt b/codeCore/src/prog8/code/target/VMTarget.kt index 458f8ff66..79c7efc44 100644 --- a/codeCore/src/prog8/code/target/VMTarget.kt +++ b/codeCore/src/prog8/code/target/VMTarget.kt @@ -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) } } diff --git a/codeCore/src/prog8/code/target/cbm/CbmMemorySizer.kt b/codeCore/src/prog8/code/target/cbm/CbmMemorySizer.kt index f2969f8c3..e1521123f 100644 --- a/codeCore/src/prog8/code/target/cbm/CbmMemorySizer.kt +++ b/codeCore/src/prog8/code/target/cbm/CbmMemorySizer.kt @@ -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) } } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt index de6f22d7d..9259874a4 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt @@ -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()}") diff --git a/codeGenCpu6502/test/Dummies.kt b/codeGenCpu6502/test/Dummies.kt index 62bfa0763..c8307d8a0 100644 --- a/codeGenCpu6502/test/Dummies.kt +++ b/codeGenCpu6502/test/Dummies.kt @@ -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) } } diff --git a/codeGenIntermediate/test/Dummies.kt b/codeGenIntermediate/test/Dummies.kt index 89f1002b2..c886bdf92 100644 --- a/codeGenIntermediate/test/Dummies.kt +++ b/codeGenIntermediate/test/Dummies.kt @@ -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) } } diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 4a0126aaa..adf8fcf6d 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -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 { diff --git a/compiler/src/prog8/compiler/astprocessing/BeforeAsmTypecastCleaner.kt b/compiler/src/prog8/compiler/astprocessing/BeforeAsmTypecastCleaner.kt index 65b160d4d..3983ff491 100644 --- a/compiler/src/prog8/compiler/astprocessing/BeforeAsmTypecastCleaner.kt +++ b/compiler/src/prog8/compiler/astprocessing/BeforeAsmTypecastCleaner.kt @@ -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) diff --git a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt index 41891e2d1..f3726d957 100644 --- a/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt +++ b/compiler/src/prog8/compiler/astprocessing/IntermediateAstMaker.kt @@ -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) diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index 7d63f5831..70a566bbb 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -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) } diff --git a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt index 2bd866892..0434ddec5 100644 --- a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt +++ b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt @@ -42,7 +42,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val return noModifications val modifications = mutableListOf() - 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() - 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() - 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() 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() - addTypecastOrCastedValueModification(modifications, assignment.value, targettype, assignment) + addTypecastOrCastedValueModification(modifications, assignment.value, targettype.dt, assignment) return modifications } else { fun castLiteral(cvalue2: NumericLiteral): List { - 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() 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 { // 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() 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() 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() - 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() 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) diff --git a/compiler/test/TestBuiltinFunctions.kt b/compiler/test/TestBuiltinFunctions.kt index 614dc2ceb..e63fbe278 100644 --- a/compiler/test/TestBuiltinFunctions.kt +++ b/compiler/test/TestBuiltinFunctions.kt @@ -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 diff --git a/compiler/test/TestCompilerOnCharLit.kt b/compiler/test/TestCompilerOnCharLit.kt index 2b9e5be40..b05bb7bb2 100644 --- a/compiler/test/TestCompilerOnCharLit.kt +++ b/compiler/test/TestCompilerOnCharLit.kt @@ -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() } 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() } 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 -> { diff --git a/compiler/test/TestGoldenRam.kt b/compiler/test/TestGoldenRam.kt index aa8be1832..afd6219bd 100644 --- a/compiler/test/TestGoldenRam.kt +++ b/compiler/test/TestGoldenRam.kt @@ -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" } } diff --git a/compiler/test/TestMemory.kt b/compiler/test/TestMemory.kt index f2bcf3f57..3ced5c357 100644 --- a/compiler/test/TestMemory.kt +++ b/compiler/test/TestMemory.kt @@ -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) diff --git a/compiler/test/TestNumericLiteral.kt b/compiler/test/TestNumericLiteral.kt index f88eb9d26..3bca47036 100644 --- a/compiler/test/TestNumericLiteral.kt +++ b/compiler/test/TestNumericLiteral.kt @@ -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 } }) diff --git a/compiler/test/TestOptimization.kt b/compiler/test/TestOptimization.kt index 533af6057..302ec0744 100644 --- a/compiler/test/TestOptimization.kt +++ b/compiler/test/TestOptimization.kt @@ -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() 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() 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() 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() diff --git a/compiler/test/TestPtNumber.kt b/compiler/test/TestPtNumber.kt index d6d188570..a8856d832 100644 --- a/compiler/test/TestPtNumber.kt +++ b/compiler/test/TestPtNumber.kt @@ -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 diff --git a/compiler/test/TestSubroutines.kt b/compiler/test/TestSubroutines.kt index 697ad9ef1..eb089f721 100644 --- a/compiler/test/TestSubroutines.kt +++ b/compiler/test/TestSubroutines.kt @@ -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().single { it.name=="asmfunc"} val func = mainBlock.statements.filterIsInstance().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) } } diff --git a/compiler/test/TestSymbolTable.kt b/compiler/test/TestSymbolTable.kt index e8e0bbf7f..ae296ba56 100644 --- a/compiler/test/TestSymbolTable.kt +++ b/compiler/test/TestSymbolTable.kt @@ -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) diff --git a/compiler/test/TestTypecasts.kt b/compiler/test/TestTypecasts.kt index bf09cd80a..061d68a4c 100644 --- a/compiler/test/TestTypecasts.kt +++ b/compiler/test/TestTypecasts.kt @@ -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() val assign1subtc = (assign1tc.expression as TypecastExpression) - assign1subtc.type shouldBe DataType.BYTE + assign1subtc.type shouldBe BaseDataType.BYTE assign1subtc.expression shouldBe instanceOf() } @@ -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") { diff --git a/compiler/test/TestZeropage.kt b/compiler/test/TestZeropage.kt index cd7c2a2b3..ad4a7008a 100644 --- a/compiler/test/TestZeropage.kt +++ b/compiler/test/TestZeropage.kt @@ -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 { zp.allocate("varname", DataType.UBYTE,null, null, errors) } - result = zp.allocate("varname2", DataType.UBYTE, null, null, errors) + shouldThrow { 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 } diff --git a/compiler/test/ast/TestConst.kt b/compiler/test/ast/TestConst.kt index 739989a50..01cb88429 100644 --- a/compiler/test/ast/TestConst.kt +++ b/compiler/test/ast/TestConst.kt @@ -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 } diff --git a/compiler/test/ast/TestIntermediateAst.kt b/compiler/test/ast/TestIntermediateAst.kt index d16011bed..ac4d1f844 100644 --- a/compiler/test/ast/TestIntermediateAst.kt +++ b/compiler/test/ast/TestIntermediateAst.kt @@ -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() @@ -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 diff --git a/compiler/test/ast/TestSubroutines.kt b/compiler/test/ast/TestSubroutines.kt index 167c1c4ed..1bbffee64 100644 --- a/compiler/test/ast/TestSubroutines.kt +++ b/compiler/test/ast/TestSubroutines.kt @@ -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().single { it.name=="asmfunc"} val func = mainBlock.statements.filterIsInstance().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().single { it.name=="asmfunc"} val func = mainBlock.statements.filterIsInstance().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 } diff --git a/compiler/test/ast/TestVariousCompilerAst.kt b/compiler/test/ast/TestVariousCompilerAst.kt index 9d55cc03d..e4f0f66b6 100644 --- a/compiler/test/ast/TestVariousCompilerAst.kt +++ b/compiler/test/ast/TestVariousCompilerAst.kt @@ -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() 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() } diff --git a/compiler/test/codegeneration/TestAsmGenSymbols.kt b/compiler/test/codegeneration/TestAsmGenSymbols.kt index 3ea33d4af..bfc34146f 100644 --- a/compiler/test/codegeneration/TestAsmGenSymbols.kt +++ b/compiler/test/codegeneration/TestAsmGenSymbols.kt @@ -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" diff --git a/compiler/test/codegeneration/TestVariousCodeGen.kt b/compiler/test/codegeneration/TestVariousCodeGen.kt index 4554d8923..8d42e6e5d 100644 --- a/compiler/test/codegeneration/TestVariousCodeGen.kt +++ b/compiler/test/codegeneration/TestVariousCodeGen.kt @@ -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() diff --git a/compiler/test/helpers/Dummies.kt b/compiler/test/helpers/Dummies.kt index 1adf368d8..63a1fa384 100644 --- a/compiler/test/helpers/Dummies.kt +++ b/compiler/test/helpers/Dummies.kt @@ -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") + } } diff --git a/compilerAst/src/prog8/ast/expressions/InferredTypes.kt b/compilerAst/src/prog8/ast/expressions/InferredTypes.kt index bc1cad27b..0272ecaf0 100644 --- a/compilerAst/src/prog8/ast/expressions/InferredTypes.kt +++ b/compilerAst/src/prog8/ast/expressions/InferredTypes.kt @@ -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 diff --git a/docs/source/todo.rst b/docs/source/todo.rst index a38656dd6..12748721c 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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