From 66574d058a0fbb809faf28d843e07b7b5f1a0bf7 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 13 Oct 2021 00:21:38 +0200 Subject: [PATCH] renamed InferredType.typeOrElse to getOr() this is closer to the convention of most functional return types --- .../compiler/BeforeAsmGenerationAstChanger.kt | 6 ++-- .../compiler/astprocessing/AstChecker.kt | 26 +++++++------- .../astprocessing/LiteralsToAutoVars.kt | 2 +- .../astprocessing/StatementReorderer.kt | 2 +- .../compiler/astprocessing/TypecastsAdder.kt | 14 ++++---- .../astprocessing/VerifyFunctionArgTypes.kt | 2 +- .../compiler/functions/BuiltinFunctions.kt | 8 ++--- .../compiler/target/cpu6502/codegen/AsmGen.kt | 6 ++-- .../cpu6502/codegen/BuiltinFunctionsAsmGen.kt | 36 +++++++++---------- .../cpu6502/codegen/ExpressionsAsmGen.kt | 14 ++++---- .../target/cpu6502/codegen/ForLoopsAsmGen.kt | 8 ++--- .../cpu6502/codegen/FunctionCallAsmGen.kt | 4 +-- .../cpu6502/codegen/PostIncrDecrAsmGen.kt | 4 +-- .../codegen/assignment/AsmAssignment.kt | 10 +++--- .../codegen/assignment/AssignmentAsmGen.kt | 4 +-- .../assignment/AugmentableAssignmentAsmGen.kt | 6 ++-- .../optimizer/ConstantFoldingOptimizer.kt | 8 ++--- .../optimizer/ConstantIdentifierReplacer.kt | 2 +- .../prog8/optimizer/ExpressionSimplifier.kt | 16 ++++----- .../src/prog8/optimizer/StatementOptimizer.kt | 2 +- compiler/test/TestCompilerOnRanges.kt | 2 +- .../prog8/ast/expressions/AstExpressions.kt | 18 +++++----- .../prog8/ast/expressions/InferredTypes.kt | 4 ++- .../src/prog8/ast/statements/AstStatements.kt | 2 +- docs/source/todo.rst | 1 - 25 files changed, 104 insertions(+), 103 deletions(-) diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index 2684cbb40..126ae7048 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -146,7 +146,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: I // see if we can remove superfluous typecasts (outside of expressions) // such as casting byte<->ubyte, word<->uword // Also the special typecast of a reference type (str, array) to an UWORD will be changed into address-of. - val sourceDt = typecast.expression.inferType(program).typeOrElse(DataType.UNDEFINED) + val sourceDt = typecast.expression.inferType(program).getOr(DataType.UNDEFINED) if (typecast.type in ByteDatatypes && sourceDt in ByteDatatypes || typecast.type in WordDatatypes && sourceDt in WordDatatypes) { if(typecast.parent !is Expression) { @@ -266,8 +266,8 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: I // if the datatype of the arguments of cmp() are different, cast the byte one to word. val arg1 = functionCallStatement.args[0] val arg2 = functionCallStatement.args[1] - val dt1 = arg1.inferType(program).typeOrElse(DataType.UNDEFINED) - val dt2 = arg2.inferType(program).typeOrElse(DataType.UNDEFINED) + val dt1 = arg1.inferType(program).getOr(DataType.UNDEFINED) + val dt2 = arg2.inferType(program).getOr(DataType.UNDEFINED) if(dt1 in ByteDatatypes) { if(dt2 in ByteDatatypes) return noModifications diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 41681ca02..b6557898b 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -79,7 +79,7 @@ internal class AstChecker(private val program: Program, if(!valueDt.isKnown) { errors.err("return value type mismatch or unknown symbol", returnStmt.value!!.position) } else { - if (expectedReturnValues[0] != valueDt.typeOrElse(DataType.UNDEFINED)) + if (expectedReturnValues[0] != valueDt.getOr(DataType.UNDEFINED)) errors.err("type $valueDt of return value doesn't match subroutine's return type ${expectedReturnValues[0]}", returnStmt.value!!.position) } } @@ -105,7 +105,7 @@ internal class AstChecker(private val program: Program, } } - val iterableDt = forLoop.iterable.inferType(program).typeOrElse(DataType.BYTE) + val iterableDt = forLoop.iterable.inferType(program).getOr(DataType.BYTE) if(iterableDt !in IterableDatatypes && forLoop.iterable !is RangeExpr) { errors.err("can only loop over an iterable type", forLoop.position) } else { @@ -414,7 +414,7 @@ internal class AstChecker(private val program: Program, if(!idt.isKnown) { errors.err("return type mismatch", assignment.value.position) } - if(stmt.returntypes.isEmpty() || (stmt.returntypes.size == 1 && stmt.returntypes.single() isNotAssignableTo idt.typeOrElse(DataType.BYTE))) { + if(stmt.returntypes.isEmpty() || (stmt.returntypes.size == 1 && stmt.returntypes.single() isNotAssignableTo idt.getOr(DataType.BYTE))) { errors.err("return type mismatch", assignment.value.position) } } @@ -479,15 +479,15 @@ internal class AstChecker(private val program: Program, if (targetDatatype.isKnown) { val constVal = assignment.value.constValue(program) if (constVal != null) { - checkValueTypeAndRange(targetDatatype.typeOrElse(DataType.BYTE), constVal) + checkValueTypeAndRange(targetDatatype.getOr(DataType.BYTE), constVal) } else { val sourceDatatype = assignment.value.inferType(program) if (sourceDatatype.isUnknown) { if (assignment.value !is FunctionCall) errors.err("assignment value is invalid or has no proper datatype", assignment.value.position) } else { - checkAssignmentCompatible(targetDatatype.typeOrElse(DataType.BYTE), assignTarget, - sourceDatatype.typeOrElse(DataType.BYTE), assignment.value, assignment.position) + checkAssignmentCompatible(targetDatatype.getOr(DataType.BYTE), assignTarget, + sourceDatatype.getOr(DataType.BYTE), assignment.value, assignment.position) } } } @@ -741,11 +741,11 @@ internal class AstChecker(private val program: Program, override fun visit(array: ArrayLiteralValue) { if(array.type.isKnown) { - if (!compilerOptions.floats && array.type.typeOrElse(DataType.UNDEFINED) in setOf(DataType.FLOAT, DataType.ARRAY_F)) { + if (!compilerOptions.floats && array.type.getOr(DataType.UNDEFINED) in setOf(DataType.FLOAT, DataType.ARRAY_F)) { errors.err("floating point used, but that is not enabled via options", array.position) } val arrayspec = ArrayIndex.forArray(array) - checkValueTypeAndRangeArray(array.type.typeOrElse(DataType.UNDEFINED), arrayspec, array) + checkValueTypeAndRangeArray(array.type.getOr(DataType.UNDEFINED), arrayspec, array) } fun isPassByReferenceElement(e: Expression): Boolean { @@ -794,7 +794,7 @@ internal class AstChecker(private val program: Program, if(!idt.isKnown) return // any error should be reported elsewhere - val dt = idt.typeOrElse(DataType.UNDEFINED) + val dt = idt.getOr(DataType.UNDEFINED) if(expr.operator=="-") { if (dt != DataType.BYTE && dt != DataType.WORD && dt != DataType.FLOAT) { errors.err("can only take negative of a signed number type", expr.position) @@ -819,8 +819,8 @@ internal class AstChecker(private val program: Program, if(!leftIDt.isKnown || !rightIDt.isKnown) return // hopefully this error will be detected elsewhere - val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED) - val rightDt = rightIDt.typeOrElse(DataType.UNDEFINED) + val leftDt = leftIDt.getOr(DataType.UNDEFINED) + val rightDt = rightIDt.getOr(DataType.UNDEFINED) when(expr.operator){ "/", "%" -> { @@ -1028,7 +1028,7 @@ internal class AstChecker(private val program: Program, if((args[0] as? AddressOf)?.identifier?.targetVarDecl(program)?.datatype == DataType.STR) { errors.err("any/all on a string is useless (is always true unless the string is empty)", position) } - if(args[0].inferType(program).typeOrElse(DataType.STR) == DataType.STR) { + if(args[0].inferType(program).getOr(DataType.STR) == DataType.STR) { errors.err("any/all on a string is useless (is always true unless the string is empty)", position) } } @@ -1157,7 +1157,7 @@ internal class AstChecker(private val program: Program, when { constvalue == null -> errors.err("choice value must be a constant", whenChoice.position) constvalue.type !in IntegerDatatypes -> errors.err("choice value must be a byte or word", whenChoice.position) - constvalue.type != conditionType.typeOrElse(DataType.UNDEFINED) -> errors.err("choice value datatype differs from condition value", whenChoice.position) + constvalue.type != conditionType.getOr(DataType.UNDEFINED) -> errors.err("choice value datatype differs from condition value", whenChoice.position) } } } else { diff --git a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt index 5b7bf6146..4e47645f2 100644 --- a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt +++ b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVars.kt @@ -38,7 +38,7 @@ internal class LiteralsToAutoVars(private val program: Program) : AstWalker() { val arrayDt = array.guessDatatype(program) if(arrayDt.isKnown) { // this array literal is part of an expression, turn it into an identifier reference - val litval2 = array.cast(arrayDt.typeOrElse(DataType.UNDEFINED)) + val litval2 = array.cast(arrayDt.getOr(DataType.UNDEFINED)) if(litval2!=null) { val vardecl2 = VarDecl.createAuto(litval2) val identifier = IdentifierReference(listOf(vardecl2.name), vardecl2.position) diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index 5be73eff7..bd12a7dc5 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -106,7 +106,7 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport is Assignment -> { val targetDt = parent.target.inferType(program) if(leftDt != targetDt) { - val cast = TypecastExpression(expr.left, targetDt.typeOrElse(DataType.UNDEFINED), true, parent.position) + val cast = TypecastExpression(expr.left, targetDt.getOr(DataType.UNDEFINED), true, parent.position) return listOf(IAstModification.ReplaceNode(expr.left, cast, expr)) } } diff --git a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt index 4f6acbdaa..7620919e9 100644 --- a/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt +++ b/compiler/src/prog8/compiler/astprocessing/TypecastsAdder.kt @@ -47,7 +47,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk val rightDt = expr.right.inferType(program) if(leftDt.isKnown && rightDt.isKnown && leftDt!=rightDt) { // determine common datatype and add typecast as required to make left and right equal types - val (commonDt, toFix) = BinaryExpression.commonDatatype(leftDt.typeOrElse(DataType.UNDEFINED), rightDt.typeOrElse(DataType.UNDEFINED), expr.left, expr.right) + val (commonDt, toFix) = BinaryExpression.commonDatatype(leftDt.getOr(DataType.UNDEFINED), rightDt.getOr(DataType.UNDEFINED), expr.left, expr.right) if(toFix!=null) { return when { toFix===expr.left -> listOf(IAstModification.ReplaceNode( @@ -66,8 +66,8 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk val valueItype = assignment.value.inferType(program) val targetItype = assignment.target.inferType(program) if(targetItype.isKnown && valueItype.isKnown) { - val targettype = targetItype.typeOrElse(DataType.UNDEFINED) - val valuetype = valueItype.typeOrElse(DataType.UNDEFINED) + val targettype = targetItype.getOr(DataType.UNDEFINED) + val valuetype = valueItype.getOr(DataType.UNDEFINED) if (valuetype != targettype) { if (valuetype isAssignableTo targettype) { if(valuetype in IterableDatatypes && targettype==DataType.UWORD) @@ -126,7 +126,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk sub.parameters.zip(call.args).forEachIndexed { index, pair -> val argItype = pair.second.inferType(program) if(argItype.isKnown) { - val argtype = argItype.typeOrElse(DataType.UNDEFINED) + val argtype = argItype.getOr(DataType.UNDEFINED) val requiredType = pair.first.type if (requiredType != argtype) { if (argtype isAssignableTo requiredType) { @@ -159,7 +159,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk func.parameters.zip(call.args).forEachIndexed { index, pair -> val argItype = pair.second.inferType(program) if (argItype.isKnown) { - val argtype = argItype.typeOrElse(DataType.UNDEFINED) + val argtype = argItype.getOr(DataType.UNDEFINED) if (pair.first.possibleDatatypes.all { argtype != it }) { for (possibleType in pair.first.possibleDatatypes) { if (argtype isAssignableTo possibleType) { @@ -191,7 +191,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk override fun after(memread: DirectMemoryRead, parent: Node): Iterable { // make sure the memory address is an uword val dt = memread.addressExpression.inferType(program) - if(dt.isKnown && dt.typeOrElse(DataType.UWORD)!=DataType.UWORD) { + if(dt.isKnown && dt.getOr(DataType.UWORD)!=DataType.UWORD) { val typecast = (memread.addressExpression as? NumericLiteralValue)?.cast(DataType.UWORD)?.valueOrZero() ?: TypecastExpression(memread.addressExpression, DataType.UWORD, true, memread.addressExpression.position) return listOf(IAstModification.ReplaceNode(memread.addressExpression, typecast, memread)) @@ -202,7 +202,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk override fun after(memwrite: DirectMemoryWrite, parent: Node): Iterable { // make sure the memory address is an uword val dt = memwrite.addressExpression.inferType(program) - if(dt.isKnown && dt.typeOrElse(DataType.UWORD)!=DataType.UWORD) { + if(dt.isKnown && dt.getOr(DataType.UWORD)!=DataType.UWORD) { val typecast = (memwrite.addressExpression as? NumericLiteralValue)?.cast(DataType.UWORD)?.valueOrZero() ?: TypecastExpression(memwrite.addressExpression, DataType.UWORD, true, memwrite.addressExpression.position) return listOf(IAstModification.ReplaceNode(memwrite.addressExpression, typecast, memwrite)) diff --git a/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt b/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt index 234f67040..e5d74ee10 100644 --- a/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt +++ b/compiler/src/prog8/compiler/astprocessing/VerifyFunctionArgTypes.kt @@ -44,7 +44,7 @@ class VerifyFunctionArgTypes(val program: Program) : IAstVisitor { val firstUnknownDt = argITypes.indexOfFirst { it.isUnknown } if(firstUnknownDt>=0) return "argument ${firstUnknownDt+1} invalid argument type" - val argtypes = argITypes.map { it.typeOrElse(DataType.UNDEFINED) } + val argtypes = argITypes.map { it.getOr(DataType.UNDEFINED) } val target = call.target.targetStatement(program) if (target is Subroutine) { if(call.args.size != target.parameters.size) diff --git a/compiler/src/prog8/compiler/functions/BuiltinFunctions.kt b/compiler/src/prog8/compiler/functions/BuiltinFunctions.kt index 0120ce69f..5affb0745 100644 --- a/compiler/src/prog8/compiler/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/compiler/functions/BuiltinFunctions.kt @@ -164,7 +164,7 @@ fun builtinFunctionReturnType(function: String, args: List, program: fun datatypeFromIterableArg(arglist: Expression): DataType { if(arglist is ArrayLiteralValue) { - val dt = arglist.value.map {it.inferType(program).typeOrElse(DataType.UNDEFINED)}.toSet() + val dt = arglist.value.map {it.inferType(program).getOr(DataType.UNDEFINED)}.toSet() if(dt.any { it !in NumericDatatypes }) { throw FatalAstException("fuction $function only accepts array of numeric values") } @@ -178,7 +178,7 @@ fun builtinFunctionReturnType(function: String, args: List, program: val idt = arglist.inferType(program) if(!idt.isKnown) throw FatalAstException("couldn't determine type of iterable $arglist") - return when(val dt = idt.typeOrElse(DataType.UNDEFINED)) { + return when(val dt = idt.getOr(DataType.UNDEFINED)) { DataType.STR, in NumericDatatypes -> dt in ArrayDatatypes -> ArrayToElementTypes.getValue(dt) else -> throw FatalAstException("function '$function' requires one argument which is an iterable") @@ -302,11 +302,11 @@ private fun builtinSizeof(args: List, position: Position, program: P return when { dt.isArray -> { val length = (target as VarDecl).arraysize!!.constIndex() ?: throw CannotEvaluateException("sizeof", "unknown array size") - val elementDt = ArrayToElementTypes.getValue(dt.typeOrElse(DataType.UNDEFINED)) + val elementDt = ArrayToElementTypes.getValue(dt.getOr(DataType.UNDEFINED)) numericLiteral(memsizer.memorySize(elementDt) * length, position) } dt.istype(DataType.STR) -> throw SyntaxError("sizeof str is undefined, did you mean len?", position) - else -> NumericLiteralValue(DataType.UBYTE, memsizer.memorySize(dt.typeOrElse(DataType.UNDEFINED)), position) + else -> NumericLiteralValue(DataType.UBYTE, memsizer.memorySize(dt.getOr(DataType.UNDEFINED)), position) } } else { throw SyntaxError("sizeof invalid argument type", position) diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt index bc476483e..c6ab9bfa9 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt @@ -1061,7 +1061,7 @@ internal class AsmGen(private val program: Program, val dt = stmt.iterations!!.inferType(program) if(!dt.isKnown) throw AssemblyError("unknown dt") - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { in ByteDatatypes -> { assignExpressionToRegister(stmt.iterations!!, RegisterOrPair.A) repeatByteCountInA(null, repeatLabel, endLabel, stmt) @@ -1193,7 +1193,7 @@ $repeatLabel lda $counterVar val conditionDt = stmt.condition.inferType(program) if(!conditionDt.isKnown) throw AssemblyError("unknown condition dt") - if(conditionDt.typeOrElse(DataType.BYTE) in ByteDatatypes) + if(conditionDt.getOr(DataType.BYTE) in ByteDatatypes) assignExpressionToRegister(stmt.condition, RegisterOrPair.A) else assignExpressionToRegister(stmt.condition, RegisterOrPair.AY) @@ -1208,7 +1208,7 @@ $repeatLabel lda $counterVar choiceBlocks.add(choiceLabel to choice.statements) for (cv in choice.values!!) { val value = (cv as NumericLiteralValue).number.toInt() - if(conditionDt.typeOrElse(DataType.BYTE) in ByteDatatypes) { + if(conditionDt.getOr(DataType.BYTE) in ByteDatatypes) { out(" cmp #${value.toHex()} | beq $choiceLabel") } else { out(""" diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt index a59d25819..2f6587c60 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt @@ -177,8 +177,8 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val private fun funcCmp(fcall: IFunctionCall) { val arg1 = fcall.args[0] val arg2 = fcall.args[1] - val dt1 = arg1.inferType(program).typeOrElse(DataType.UNDEFINED) - val dt2 = arg2.inferType(program).typeOrElse(DataType.UNDEFINED) + val dt1 = arg1.inferType(program).getOr(DataType.UNDEFINED) + val dt2 = arg2.inferType(program).getOr(DataType.UNDEFINED) if(dt1 in ByteDatatypes) { if(dt2 in ByteDatatypes) { when (arg2) { @@ -368,7 +368,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val private fun funcRor2(fcall: IFunctionCall) { val what = fcall.args.single() val dt = what.inferType(program) - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.UBYTE -> { when (what) { is ArrayIndexedExpression -> { @@ -411,7 +411,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val private fun funcRor(fcall: IFunctionCall) { val what = fcall.args.single() val dt = what.inferType(program) - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.UBYTE -> { when (what) { is ArrayIndexedExpression -> { @@ -469,7 +469,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val private fun funcRol2(fcall: IFunctionCall) { val what = fcall.args.single() val dt = what.inferType(program) - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.UBYTE -> { when (what) { is ArrayIndexedExpression -> { @@ -512,7 +512,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val private fun funcRol(fcall: IFunctionCall) { val what = fcall.args.single() val dt = what.inferType(program) - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.UBYTE -> { when (what) { is ArrayIndexedExpression -> { @@ -586,7 +586,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val translateArguments(fcall.args, func, scope) val dt = fcall.args.single().inferType(program) if(resultToStack) { - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.UBYTE -> asmgen.out(" jsr prog8_lib.func_sign_ub_stack") DataType.BYTE -> asmgen.out(" jsr prog8_lib.func_sign_b_stack") DataType.UWORD -> asmgen.out(" jsr prog8_lib.func_sign_uw_stack") @@ -595,7 +595,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val else -> throw AssemblyError("weird type $dt") } } else { - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.UBYTE -> asmgen.out(" jsr prog8_lib.func_sign_ub_into_A") DataType.BYTE -> asmgen.out(" jsr prog8_lib.func_sign_b_into_A") DataType.UWORD -> asmgen.out(" jsr prog8_lib.func_sign_uw_into_A") @@ -611,14 +611,14 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val outputAddressAndLenghtOfArray(fcall.args[0]) val dt = fcall.args.single().inferType(program) if(resultToStack) { - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${function.name}_b_stack") DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${function.name}_w_stack") DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${function.name}_f_stack") else -> throw AssemblyError("weird type $dt") } } else { - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${function.name}_b_into_A") DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${function.name}_w_into_A") DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${function.name}_f_into_A") @@ -632,7 +632,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val outputAddressAndLenghtOfArray(fcall.args[0]) val dt = fcall.args.single().inferType(program) if(resultToStack) { - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${function.name}_ub_stack") DataType.ARRAY_B -> asmgen.out(" jsr prog8_lib.func_${function.name}_b_stack") DataType.ARRAY_UW -> asmgen.out(" jsr prog8_lib.func_${function.name}_uw_stack") @@ -641,7 +641,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val else -> throw AssemblyError("weird type $dt") } } else { - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.ARRAY_UB, DataType.STR -> { asmgen.out(" jsr prog8_lib.func_${function.name}_ub_into_A") assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, scope, program, asmgen), CpuRegister.A) @@ -671,7 +671,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val outputAddressAndLenghtOfArray(fcall.args[0]) val dt = fcall.args.single().inferType(program) if(resultToStack) { - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_sum_ub_stack") DataType.ARRAY_B -> asmgen.out(" jsr prog8_lib.func_sum_b_stack") DataType.ARRAY_UW -> asmgen.out(" jsr prog8_lib.func_sum_uw_stack") @@ -680,7 +680,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val else -> throw AssemblyError("weird type $dt") } } else { - when (dt.typeOrElse(DataType.UNDEFINED)) { + when (dt.getOr(DataType.UNDEFINED)) { DataType.ARRAY_UB, DataType.STR -> { asmgen.out(" jsr prog8_lib.func_sum_ub_into_AY") assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, scope, program, asmgen), RegisterOrPair.AY) @@ -825,7 +825,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val val elementIDt = first.inferType(program) if(!elementIDt.isKnown) throw AssemblyError("unknown dt") - val elementDt = elementIDt.typeOrElse(DataType.UNDEFINED) + val elementDt = elementIDt.getOr(DataType.UNDEFINED) val firstNum = first.indexer.indexExpr as? NumericLiteralValue val firstVar = first.indexer.indexExpr as? IdentifierReference @@ -858,7 +858,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val } } - when(val datatype: DataType = first.inferType(program).typeOrElse(DataType.UNDEFINED)) { + when(val datatype: DataType = first.inferType(program).getOr(DataType.UNDEFINED)) { in ByteDatatypes, in WordDatatypes -> { asmgen.assignExpressionToVariable(first, "P8ZP_SCRATCH_W1", datatype, null) asmgen.assignExpressionToVariable(second, "P8ZP_SCRATCH_W2", datatype, null) @@ -1128,7 +1128,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val private fun funcAbs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) { translateArguments(fcall.args, func, scope) - val dt = fcall.args.single().inferType(program).typeOrElse(DataType.UNDEFINED) + val dt = fcall.args.single().inferType(program).getOr(DataType.UNDEFINED) if(resultToStack) { when (dt) { in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b_stack") @@ -1474,7 +1474,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val } private fun translateArguments(args: MutableList, signature: FSignature, scope: Subroutine?) { - val callConv = signature.callConvention(args.map { it.inferType(program).typeOrElse(DataType.UNDEFINED) }) + val callConv = signature.callConvention(args.map { it.inferType(program).getOr(DataType.UNDEFINED) }) fun getSourceForFloat(value: Expression): AsmAssignSource { return when (value) { diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt index e943e8c93..5af0c5a99 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt @@ -57,7 +57,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge val idt = left.inferType(program) if(!idt.isKnown) throw AssemblyError("unknown dt") - val dt = idt.typeOrElse(DataType.UNDEFINED) + val dt = idt.getOr(DataType.UNDEFINED) when (operator) { "==" -> { // if the left operand is an expression, and the right is 0, we can just evaluate that expression, @@ -1626,7 +1626,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge private fun translateExpression(typecast: TypecastExpression) { translateExpression(typecast.expression) - when(typecast.expression.inferType(program).typeOrElse(DataType.UNDEFINED)) { + when(typecast.expression.inferType(program).getOr(DataType.UNDEFINED)) { DataType.UBYTE -> { when(typecast.type) { DataType.UBYTE, DataType.BYTE -> {} @@ -1757,7 +1757,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge private fun translateExpression(expr: IdentifierReference) { val varname = asmgen.asmVariableName(expr) - when(expr.inferType(program).typeOrElse(DataType.UNDEFINED)) { + when(expr.inferType(program).getOr(DataType.UNDEFINED)) { DataType.UBYTE, DataType.BYTE -> { asmgen.out(" lda $varname | sta P8ESTACK_LO,x | dex") } @@ -1781,8 +1781,8 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge if(!leftIDt.isKnown || !rightIDt.isKnown) throw AssemblyError("can't infer type of both expression operands") - val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED) - val rightDt = rightIDt.typeOrElse(DataType.UNDEFINED) + val leftDt = leftIDt.getOr(DataType.UNDEFINED) + val rightDt = rightIDt.getOr(DataType.UNDEFINED) // see if we can apply some optimized routines // TODO avoid using evaluation on stack everywhere when(expr.operator) { @@ -2108,7 +2108,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge val itype = expr.inferType(program) if(!itype.isKnown) throw AssemblyError("unknown dt") - val type = itype.typeOrElse(DataType.UNDEFINED) + val type = itype.getOr(DataType.UNDEFINED) when(expr.operator) { "+" -> {} "-" -> { @@ -2146,7 +2146,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge val elementIDt = arrayExpr.inferType(program) if(!elementIDt.isKnown) throw AssemblyError("unknown dt") - val elementDt = elementIDt.typeOrElse(DataType.UNDEFINED) + val elementDt = elementIDt.getOr(DataType.UNDEFINED) val arrayVarName = asmgen.asmVariableName(arrayExpr.arrayvar) val constIndexNum = arrayExpr.indexer.constIndex() if(constIndexNum!=null) { diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt index 29d8fd96a..b35e3656c 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt @@ -22,13 +22,13 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen: is RangeExpr -> { val range = (stmt.iterable as RangeExpr).toConstantIntegerRange(asmgen.options.compTarget) if(range==null) { - translateForOverNonconstRange(stmt, iterableDt.typeOrElse(DataType.UNDEFINED), stmt.iterable as RangeExpr) + translateForOverNonconstRange(stmt, iterableDt.getOr(DataType.UNDEFINED), stmt.iterable as RangeExpr) } else { - translateForOverConstRange(stmt, iterableDt.typeOrElse(DataType.UNDEFINED), range) + translateForOverConstRange(stmt, iterableDt.getOr(DataType.UNDEFINED), range) } } is IdentifierReference -> { - translateForOverIterableVar(stmt, iterableDt.typeOrElse(DataType.UNDEFINED), stmt.iterable as IdentifierReference) + translateForOverIterableVar(stmt, iterableDt.getOr(DataType.UNDEFINED), stmt.iterable as IdentifierReference) } else -> throw AssemblyError("can't iterate over ${stmt.iterable.javaClass} - should have been replaced by a variable") } @@ -589,5 +589,5 @@ $loopLabel""") } private fun assignLoopvar(stmt: ForLoop, range: RangeExpr) = - asmgen.assignExpressionToVariable(range.from, asmgen.asmVariableName(stmt.loopVar), stmt.loopVarDt(program).typeOrElse(DataType.UNDEFINED), stmt.definingSubroutine) + asmgen.assignExpressionToVariable(range.from, asmgen.asmVariableName(stmt.loopVar), stmt.loopVarDt(program).getOr(DataType.UNDEFINED), stmt.definingSubroutine) } diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt index 5e1774035..62a7cd155 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt @@ -252,7 +252,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg val valueIDt = value.inferType(program) if(!valueIDt.isKnown) throw AssemblyError("unknown dt") - val valueDt = valueIDt.typeOrElse(DataType.UNDEFINED) + val valueDt = valueIDt.getOr(DataType.UNDEFINED) if(!isArgumentTypeCompatible(valueDt, parameter.value.type)) throw AssemblyError("argument type incompatible") @@ -265,7 +265,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg val valueIDt = value.inferType(program) if(!valueIDt.isKnown) throw AssemblyError("unknown dt") - val valueDt = valueIDt.typeOrElse(DataType.UNDEFINED) + val valueDt = valueIDt.getOr(DataType.UNDEFINED) if(!isArgumentTypeCompatible(valueDt, parameter.value.type)) throw AssemblyError("argument type incompatible") diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/PostIncrDecrAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/PostIncrDecrAsmGen.kt index 55ac0220a..e8e9f81e8 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/PostIncrDecrAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/PostIncrDecrAsmGen.kt @@ -19,7 +19,7 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg when { targetIdent!=null -> { val what = asmgen.asmVariableName(targetIdent) - when (stmt.target.inferType(program).typeOrElse(DataType.UNDEFINED)) { + when (stmt.target.inferType(program).getOr(DataType.UNDEFINED)) { in ByteDatatypes -> asmgen.out(if (incr) " inc $what" else " dec $what") in WordDatatypes -> { if(incr) @@ -65,7 +65,7 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg } targetArrayIdx!=null -> { val asmArrayvarname = asmgen.asmVariableName(targetArrayIdx.arrayvar) - val elementDt = targetArrayIdx.inferType(program).typeOrElse(DataType.UNDEFINED) + val elementDt = targetArrayIdx.inferType(program).getOr(DataType.UNDEFINED) val constIndex = targetArrayIdx.indexer.constIndex() if(constIndex!=null) { val indexValue = constIndex * program.memsizer.memorySize(elementDt) diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt index 8b7c55c8b..b9e490a50 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AsmAssignment.kt @@ -59,7 +59,7 @@ internal class AsmAssignTarget(val kind: TargetStorageKind, val idt = inferType(program) if(!idt.isKnown) throw AssemblyError("unknown dt") - val dt = idt.typeOrElse(DataType.UNDEFINED) + val dt = idt.getOr(DataType.UNDEFINED) when { identifier != null -> AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, dt, assign.definingSubroutine, variableAsmName = asmgen.asmVariableName(identifier!!), origAstTarget = this) arrayindexed != null -> AsmAssignTarget(TargetStorageKind.ARRAY, program, asmgen, dt, assign.definingSubroutine, array = arrayindexed, origAstTarget = this) @@ -132,7 +132,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind, is StringLiteralValue -> throw AssemblyError("string literal value should not occur anymore for asm generation") is ArrayLiteralValue -> throw AssemblyError("array literal value should not occur anymore for asm generation") is IdentifierReference -> { - val dt = value.inferType(program).typeOrElse(DataType.UNDEFINED) + val dt = value.inferType(program).getOr(DataType.UNDEFINED) val varName=asmgen.asmVariableName(value) // special case: "cx16.r[0-15]" are 16-bits virtual registers of the commander X16 system if(dt == DataType.UWORD && varName.lowercase().startsWith("cx16.r")) { @@ -147,7 +147,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind, AsmAssignSource(SourceStorageKind.MEMORY, program, asmgen, DataType.UBYTE, memory = value) } is ArrayIndexedExpression -> { - val dt = value.inferType(program).typeOrElse(DataType.UNDEFINED) + val dt = value.inferType(program).getOr(DataType.UNDEFINED) AsmAssignSource(SourceStorageKind.ARRAY, program, asmgen, dt, array = value) } is FunctionCall -> { @@ -162,7 +162,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind, val returnType = value.inferType(program) if(!returnType.isKnown) throw AssemblyError("unknown dt") - AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, returnType.typeOrElse(DataType.UNDEFINED), expression = value) + AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, returnType.getOr(DataType.UNDEFINED), expression = value) } else -> { throw AssemblyError("weird call") @@ -173,7 +173,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind, val dt = value.inferType(program) if(!dt.isKnown) throw AssemblyError("unknown dt") - AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, dt.typeOrElse(DataType.UNDEFINED), expression = value) + AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, dt.getOr(DataType.UNDEFINED), expression = value) } } } diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt index 9abc3120f..ffe867104 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt @@ -217,7 +217,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen val returntype = builtinFunctionReturnType(sub.name, value.args, program) if(!returntype.isKnown) throw AssemblyError("unknown dt") - when(returntype.typeOrElse(DataType.UNDEFINED)) { + when(returntype.getOr(DataType.UNDEFINED)) { in ByteDatatypes -> assignRegisterByte(assign.target, CpuRegister.A) // function's byte result is in A in WordDatatypes -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) // function's word result is in AY DataType.STR -> { @@ -299,7 +299,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen val valueIDt = value.inferType(program) if(!valueIDt.isKnown) throw AssemblyError("unknown dt") - val valueDt = valueIDt.typeOrElse(DataType.UNDEFINED) + val valueDt = valueIDt.getOr(DataType.UNDEFINED) if(valueDt==targetDt) throw AssemblyError("type cast to identical dt should have been removed") diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt index c940ab5b6..c034afeab 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -25,7 +25,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, val itype = value.inferType(program) if(!itype.isKnown) throw AssemblyError("unknown dt") - val type = itype.typeOrElse(DataType.UNDEFINED) + val type = itype.getOr(DataType.UNDEFINED) when (value.operator) { "+" -> {} "-" -> inplaceNegate(assign.target, type) @@ -280,7 +280,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, val childIDt = value.expression.inferType(program) if(!childIDt.isKnown) throw AssemblyError("unknown dt") - val childDt = childIDt.typeOrElse(DataType.UNDEFINED) + val childDt = childIDt.getOr(DataType.UNDEFINED) if (value.type!=DataType.FLOAT && (value.type.equalsSize(childDt) || value.type.largerThan(childDt))) { // this typecast is redundant here; the rest of the code knows how to deal with the uncasted value. // (works for integer types, not for float.) @@ -1218,7 +1218,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, val valueiDt = value.inferType(program) if(!valueiDt.isKnown) throw AssemblyError("unknown dt") - val valueDt = valueiDt.typeOrElse(DataType.UNDEFINED) + val valueDt = valueiDt.getOr(DataType.UNDEFINED) fun multiplyVarByWordInAY() { asmgen.out(""" diff --git a/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt b/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt index 9b6fc280a..0640ead82 100644 --- a/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt +++ b/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt @@ -105,7 +105,7 @@ internal class ConstantFoldingOptimizer(private val program: Program) : AstWalke // optimize various simple cases of ** : // optimize away 1 ** x into just 1 and 0 ** x into just 0 // optimize 2 ** x into (1< { val value = NumericLiteralValue(leftDt, 0, expr.position) @@ -120,11 +120,11 @@ internal class ConstantFoldingOptimizer(private val program: Program) : AstWalke val value = NumericLiteralValue(leftDt, 2.0.pow(rightconst.number.toDouble()), expr.position) modifications += IAstModification.ReplaceNode(expr, value, parent) } else { - val rightDt = expr.right.inferType(program).typeOrElse(DataType.UNDEFINED) + val rightDt = expr.right.inferType(program).getOr(DataType.UNDEFINED) if(leftDt in IntegerDatatypes && rightDt in IntegerDatatypes) { val targetDt = when (parent) { - is Assignment -> parent.target.inferType(program).typeOrElse(DataType.UNDEFINED) + is Assignment -> parent.target.inferType(program).getOr(DataType.UNDEFINED) is VarDecl -> parent.datatype else -> leftDt } @@ -186,7 +186,7 @@ internal class ConstantFoldingOptimizer(private val program: Program) : AstWalke } else { val arrayDt = array.guessDatatype(program) if (arrayDt.isKnown) { - val newArray = array.cast(arrayDt.typeOrElse(DataType.UNDEFINED)) + val newArray = array.cast(arrayDt.getOr(DataType.UNDEFINED)) if (newArray != null && newArray != array) return listOf(IAstModification.ReplaceNode(array, newArray, parent)) } diff --git a/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt b/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt index e95ef497f..4429ffe66 100644 --- a/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt +++ b/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt @@ -164,7 +164,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private errors.err("range expression size doesn't match declared array size", decl.value?.position!!) val constRange = rangeExpr.toConstantIntegerRange(compTarget) if(constRange!=null) { - val eltType = rangeExpr.inferType(program).typeOrElse(DataType.UBYTE) + val eltType = rangeExpr.inferType(program).getOr(DataType.UBYTE) val newValue = if(eltType in ByteDatatypes) { ArrayLiteralValue(InferredTypes.InferredType.known(decl.datatype), constRange.map { NumericLiteralValue(eltType, it.toShort(), decl.value!!.position) }.toTypedArray(), diff --git a/compiler/src/prog8/optimizer/ExpressionSimplifier.kt b/compiler/src/prog8/optimizer/ExpressionSimplifier.kt index ecc3f3d66..c33918774 100644 --- a/compiler/src/prog8/optimizer/ExpressionSimplifier.kt +++ b/compiler/src/prog8/optimizer/ExpressionSimplifier.kt @@ -134,8 +134,8 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker() )) } - val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED) - val rightDt = rightIDt.typeOrElse(DataType.UNDEFINED) + val leftDt = leftIDt.getOr(DataType.UNDEFINED) + val rightDt = rightIDt.getOr(DataType.UNDEFINED) if (expr.operator == "+" || expr.operator == "-" && leftVal == null && rightVal == null @@ -309,7 +309,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker() // useless msb() of byte value that was typecasted to word, replace with 0 return listOf(IAstModification.ReplaceNode( functionCall, - NumericLiteralValue(valueDt.typeOrElse(DataType.UBYTE), 0, arg.expression.position), + NumericLiteralValue(valueDt.getOr(DataType.UBYTE), 0, arg.expression.position), parent)) } } else { @@ -318,7 +318,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker() // useless msb() of byte value, replace with 0 return listOf(IAstModification.ReplaceNode( functionCall, - NumericLiteralValue(argDt.typeOrElse(DataType.UBYTE), 0, arg.position), + NumericLiteralValue(argDt.getOr(DataType.UBYTE), 0, arg.position), parent)) } } @@ -489,7 +489,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker() val idt = expr.inferType(program) if(!idt.isKnown) throw FatalAstException("unknown dt") - return NumericLiteralValue(idt.typeOrElse(DataType.UNDEFINED), 0, expr.position) + return NumericLiteralValue(idt.getOr(DataType.UNDEFINED), 0, expr.position) } else if (cv in powersOfTwo) { expr.operator = "&" expr.right = NumericLiteralValue.optimalInteger(cv!!.toInt()-1, expr.position) @@ -513,7 +513,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker() val leftIDt = expr.left.inferType(program) if (!leftIDt.isKnown) return null - val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED) + val leftDt = leftIDt.getOr(DataType.UNDEFINED) when (cv) { -1.0 -> { // '/' -> -left @@ -621,7 +621,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker() val targetIDt = expr.left.inferType(program) if(!targetIDt.isKnown) throw FatalAstException("unknown dt") - when (val targetDt = targetIDt.typeOrElse(DataType.UNDEFINED)) { + when (val targetDt = targetIDt.getOr(DataType.UNDEFINED)) { DataType.UBYTE, DataType.BYTE -> { if (amount >= 8) { return NumericLiteralValue(targetDt, 0, expr.position) @@ -656,7 +656,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker() val idt = expr.left.inferType(program) if(!idt.isKnown) throw FatalAstException("unknown dt") - when (idt.typeOrElse(DataType.UNDEFINED)) { + when (idt.getOr(DataType.UNDEFINED)) { DataType.UBYTE -> { if (amount >= 8) { return NumericLiteralValue.optimalInteger(0, expr.position) diff --git a/compiler/src/prog8/optimizer/StatementOptimizer.kt b/compiler/src/prog8/optimizer/StatementOptimizer.kt index e4b49efc2..c2ce8452d 100644 --- a/compiler/src/prog8/optimizer/StatementOptimizer.kt +++ b/compiler/src/prog8/optimizer/StatementOptimizer.kt @@ -373,7 +373,7 @@ internal class StatementOptimizer(private val program: Program, throw FatalAstException("can't infer type of assignment target") // optimize binary expressions a bit - val targetDt = targetIDt.typeOrElse(DataType.UNDEFINED) + val targetDt = targetIDt.getOr(DataType.UNDEFINED) val bexpr=assignment.value as? BinaryExpression if(bexpr!=null) { val rightCv = bexpr.right.constValue(program)?.number?.toDouble() diff --git a/compiler/test/TestCompilerOnRanges.kt b/compiler/test/TestCompilerOnRanges.kt index 5fd01a954..51f0b4128 100644 --- a/compiler/test/TestCompilerOnRanges.kt +++ b/compiler/test/TestCompilerOnRanges.kt @@ -257,7 +257,7 @@ class TestCompilerOnRanges { .map { it.iterable } .filterIsInstance()[0] - assertEquals(DataType.STR, iterable.inferType(program).typeOrElse(DataType.UNDEFINED)) + assertEquals(DataType.STR, iterable.inferType(program).getOr(DataType.UNDEFINED)) } } diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index d79096a17..a6c2a876c 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -88,14 +88,14 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid return when(operator) { "+" -> inferred "~", "not" -> { - when(inferred.typeOrElse(DataType.UNDEFINED)) { + when(inferred.getOr(DataType.UNDEFINED)) { in ByteDatatypes -> InferredTypes.knownFor(DataType.UBYTE) in WordDatatypes -> InferredTypes.knownFor(DataType.UWORD) else -> inferred } } "-" -> { - when(inferred.typeOrElse(DataType.UNDEFINED)) { + when(inferred.getOr(DataType.UNDEFINED)) { in ByteDatatypes -> InferredTypes.knownFor(DataType.BYTE) in WordDatatypes -> InferredTypes.knownFor(DataType.WORD) else -> inferred @@ -155,8 +155,8 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex try { InferredTypes.knownFor( commonDatatype( - leftDt.typeOrElse(DataType.BYTE), - rightDt.typeOrElse(DataType.BYTE), + leftDt.getOr(DataType.BYTE), + rightDt.getOr(DataType.BYTE), null, null ).first ) @@ -597,7 +597,7 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be fun memsize(memsizer: IMemSizer): Int { if(type.isKnown) { - val eltType = ArrayToElementTypes.getValue(type.typeOrElse(DataType.UNDEFINED)) + val eltType = ArrayToElementTypes.getValue(type.getOr(DataType.UNDEFINED)) return memsizer.memorySize(eltType) * value.size } else throw IllegalArgumentException("array datatype is not yet known") @@ -613,14 +613,14 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be return if(!loopvarDt.isArrayElement) InferredTypes.InferredType.unknown() else - InferredTypes.InferredType.known(ElementToArrayTypes.getValue(loopvarDt.typeOrElse(DataType.UNDEFINED))) + InferredTypes.InferredType.known(ElementToArrayTypes.getValue(loopvarDt.getOr(DataType.UNDEFINED))) } } // otherwise, select the "biggegst" datatype based on the elements in the array. val datatypesInArray = value.map { it.inferType(program) } require(datatypesInArray.isNotEmpty() && datatypesInArray.all { it.isKnown }) { "can't determine type of empty array" } - val dts = datatypesInArray.map { it.typeOrElse(DataType.UNDEFINED) } + val dts = datatypesInArray.map { it.getOr(DataType.UNDEFINED) } return when { DataType.FLOAT in dts -> InferredTypes.InferredType.known(DataType.ARRAY_F) DataType.STR in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UW) @@ -705,8 +705,8 @@ class RangeExpr(var from: Expression, fromDt istype DataType.WORD || toDt istype DataType.WORD -> InferredTypes.knownFor(DataType.ARRAY_W) fromDt istype DataType.BYTE || toDt istype DataType.BYTE -> InferredTypes.knownFor(DataType.ARRAY_B) else -> { - val fdt = fromDt.typeOrElse(DataType.UNDEFINED) - val tdt = toDt.typeOrElse(DataType.UNDEFINED) + val fdt = fromDt.getOr(DataType.UNDEFINED) + val tdt = toDt.getOr(DataType.UNDEFINED) if(fdt largerThan tdt) InferredTypes.knownFor(ElementToArrayTypes.getValue(fdt)) else diff --git a/compilerAst/src/prog8/ast/expressions/InferredTypes.kt b/compilerAst/src/prog8/ast/expressions/InferredTypes.kt index 9ea162094..857c273f6 100644 --- a/compilerAst/src/prog8/ast/expressions/InferredTypes.kt +++ b/compilerAst/src/prog8/ast/expressions/InferredTypes.kt @@ -11,7 +11,9 @@ object InferredTypes { } val isKnown = datatype!=null && datatype!=DataType.UNDEFINED - fun typeOrElse(alternative: DataType) = if(isUnknown || isVoid) alternative else datatype!! + fun getOr(default: DataType) = if(isUnknown || isVoid) default else datatype!! + fun getOrElse(transform: (InferredType) -> DataType): DataType = + if(isUnknown || isVoid) transform(this) else datatype!! infix fun istype(type: DataType): Boolean = if(isUnknown || isVoid) false else this.datatype==type companion object { diff --git a/compilerAst/src/prog8/ast/statements/AstStatements.kt b/compilerAst/src/prog8/ast/statements/AstStatements.kt index 452b92fd4..40d099cd1 100644 --- a/compilerAst/src/prog8/ast/statements/AstStatements.kt +++ b/compilerAst/src/prog8/ast/statements/AstStatements.kt @@ -181,7 +181,7 @@ open class VarDecl(val type: VarDeclType, if(!array.type.isKnown) throw FatalAstException("unknown dt") else - array.type.typeOrElse(DataType.UNDEFINED) + array.type.getOr(DataType.UNDEFINED) val declaredType = ArrayToElementTypes.getValue(arrayDt) val arraysize = ArrayIndex.forArray(array) return VarDecl(VarDeclType.VAR, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, array, diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 53215de3e..067783ebd 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -8,7 +8,6 @@ For next release - can Position.file be a Path- making the source variable for nodes unnecessary? -- refactor code to improve testability and other things, see [CompilerDevelopment](CompilerDevelopment.md) - simplify cx16.joystick_get2() once this cx16 rom issue is resolved: https://github.com/commanderx16/x16-rom/issues/203 (I hope this will still be included into the final v39 roms release for the cx16)