code cleanups

This commit is contained in:
Irmen de Jong 2019-08-22 22:06:21 +02:00
parent b79af624ae
commit 2d768c3f28
12 changed files with 43 additions and 59 deletions

View File

@ -160,7 +160,9 @@ interface INameScope {
} }
} }
interface IAssignable {} interface IAssignable {
// just a tag for now
}
/*********** Everything starts from here, the Program; zero or more modules *************/ /*********** Everything starts from here, the Program; zero or more modules *************/

View File

@ -1,12 +1,12 @@
package prog8.ast.expressions package prog8.ast.expressions
import prog8.ast.base.DataType import prog8.ast.base.DataType
import java.util.*
object InferredTypes { object InferredTypes {
class InferredType private constructor(val isUnknown: Boolean, val isVoid: Boolean, private var datatype: DataType?) { class InferredType private constructor(val isUnknown: Boolean, val isVoid: Boolean, private var datatype: DataType?) {
init { init {
if(datatype!=null && (isUnknown || isVoid)) require(!(datatype!=null && (isUnknown || isVoid))) { "invalid combination of args" }
throw IllegalArgumentException("invalid combination of args")
} }
val isKnown = datatype!=null val isKnown = datatype!=null
@ -32,6 +32,8 @@ object InferredTypes {
else -> "<unknown>" else -> "<unknown>"
} }
} }
override fun hashCode(): Int = Objects.hash(isVoid, datatype)
} }
private val unknownInstance = InferredType.unknown() private val unknownInstance = InferredType.unknown()

View File

@ -1,3 +1,5 @@
@file:Suppress("DuplicatedCode")
package prog8.ast.processing package prog8.ast.processing
import prog8.ast.IFunctionCall import prog8.ast.IFunctionCall
@ -945,9 +947,8 @@ internal class AstChecker(private val program: Program,
if(dt !in NumericDatatypes && dt !in ArrayDatatypes) if(dt !in NumericDatatypes && dt !in ArrayDatatypes)
checkResult.add(SyntaxError("can only increment or decrement a byte/float/word", postIncrDecr.position)) checkResult.add(SyntaxError("can only increment or decrement a byte/float/word", postIncrDecr.position))
} }
} else if(postIncrDecr.target.memoryAddress != null) {
// a memory location can always be ++/--
} }
// else if(postIncrDecr.target.memoryAddress != null) { } // a memory location can always be ++/--
super.visit(postIncrDecr) super.visit(postIncrDecr)
} }
@ -1231,11 +1232,11 @@ internal class AstChecker(private val program: Program,
} }
val array = value.value.map { val array = value.value.map {
if(it is NumericLiteralValue) when (it) {
it.number.toInt() is NumericLiteralValue -> it.number.toInt()
else if(it is AddressOf) is AddressOf -> it.identifier.heapId(program.namespace)
it.identifier.heapId(program.namespace) else -> -9999999
else -9999999 }
} }
val correct: Boolean val correct: Boolean
when (type) { when (type) {

View File

@ -219,15 +219,8 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
val subroutine = returnStmt.definingSubroutine()!! val subroutine = returnStmt.definingSubroutine()!!
if(subroutine.returntypes.size!=1) if(subroutine.returntypes.size!=1)
return returnStmt // mismatch in number of return values, error will be printed later. return returnStmt // mismatch in number of return values, error will be printed later.
val newValue: Expression
val lval = returnStmt.value as? NumericLiteralValue val lval = returnStmt.value as? NumericLiteralValue
if(lval!=null) { returnStmt.value = lval?.cast(subroutine.returntypes.single()) ?: returnStmt.value!!
newValue = lval.cast(subroutine.returntypes.single())
} else {
newValue = returnStmt.value!!
}
returnStmt.value = newValue
} }
return super.visit(returnStmt) return super.visit(returnStmt)
} }
@ -236,18 +229,19 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
val array = super.visit(arrayLiteral) val array = super.visit(arrayLiteral)
if(array is ArrayLiteralValue) { if(array is ArrayLiteralValue) {
val vardecl = array.parent as? VarDecl val vardecl = array.parent as? VarDecl
return if (vardecl!=null) { return when {
fixupArrayDatatype(array, vardecl, program) vardecl!=null -> fixupArrayDatatype(array, vardecl, program)
} else if(array.heapId!=null) { array.heapId!=null -> {
// fix the datatype of the array (also on the heap) to the 'biggest' datatype in the array // fix the datatype of the array (also on the heap) to the 'biggest' datatype in the array
// (we don't know the desired datatype here exactly so we guess) // (we don't know the desired datatype here exactly so we guess)
val datatype = determineArrayDt(array.value) val datatype = determineArrayDt(array.value)
val litval2 = array.cast(datatype)!! val litval2 = array.cast(datatype)!!
litval2.parent = array.parent litval2.parent = array.parent
// finally, replace the literal array by a identifier reference. // finally, replace the literal array by a identifier reference.
makeIdentifierFromRefLv(litval2) makeIdentifierFromRefLv(litval2)
} else }
array else -> array
}
} }
return array return array
} }
@ -272,8 +266,7 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
private fun determineArrayDt(array: Array<Expression>): DataType { private fun determineArrayDt(array: Array<Expression>): DataType {
val datatypesInArray = array.map { it.inferType(program) } val datatypesInArray = array.map { it.inferType(program) }
if(datatypesInArray.isEmpty() || datatypesInArray.any { !it.isKnown }) require(datatypesInArray.isNotEmpty() && datatypesInArray.all { it.isKnown }) { "can't determine type of empty array" }
throw IllegalArgumentException("can't determine type of empty array")
val dts = datatypesInArray.map { it.typeOrElse(DataType.STRUCT) } val dts = datatypesInArray.map { it.typeOrElse(DataType.STRUCT) }
return when { return when {
DataType.FLOAT in dts -> DataType.ARRAY_F DataType.FLOAT in dts -> DataType.ARRAY_F

View File

@ -142,8 +142,7 @@ interface IAstModifyingVisitor {
} }
fun visit(forLoop: ForLoop): Statement { fun visit(forLoop: ForLoop): Statement {
val newloopvar = forLoop.loopVar?.accept(this) when(val newloopvar = forLoop.loopVar?.accept(this)) {
when(newloopvar) {
is IdentifierReference -> forLoop.loopVar = newloopvar is IdentifierReference -> forLoop.loopVar = newloopvar
null -> forLoop.loopVar = null null -> forLoop.loopVar = null
else -> throw FatalAstException("can't change class of loopvar") else -> throw FatalAstException("can't change class of loopvar")
@ -179,8 +178,7 @@ interface IAstModifyingVisitor {
} }
fun visit(assignTarget: AssignTarget): AssignTarget { fun visit(assignTarget: AssignTarget): AssignTarget {
val ident = assignTarget.identifier?.accept(this) when (val ident = assignTarget.identifier?.accept(this)) {
when (ident) {
is IdentifierReference -> assignTarget.identifier = ident is IdentifierReference -> assignTarget.identifier = ident
null -> assignTarget.identifier = null null -> assignTarget.identifier = null
else -> throw FatalAstException("can't change class of assign target identifier") else -> throw FatalAstException("can't change class of assign target identifier")

View File

@ -1,6 +1,5 @@
package prog8.compiler package prog8.compiler
import prog8.ast.expressions.AddressOf
import java.io.File import java.io.File
import java.io.InputStream import java.io.InputStream
import java.nio.file.Path import java.nio.file.Path
@ -24,8 +23,6 @@ enum class ZeropageType {
DONTUSE DONTUSE
} }
data class IntegerOrAddressOf(val integer: Int?, val addressOf: AddressOf?)
data class CompilationOptions(val output: OutputType, data class CompilationOptions(val output: OutputType,
val launcher: LauncherType, val launcher: LauncherType,
val zeropage: ZeropageType, val zeropage: ZeropageType,

View File

@ -820,8 +820,7 @@ internal class AsmGen(val program: Program,
} }
internal fun translateArrayIndexIntoA(expr: ArrayIndexedExpression) { internal fun translateArrayIndexIntoA(expr: ArrayIndexedExpression) {
val index = expr.arrayspec.index when (val index = expr.arrayspec.index) {
when (index) {
is NumericLiteralValue -> throw AssemblyError("this should be optimized directly") is NumericLiteralValue -> throw AssemblyError("this should be optimized directly")
is RegisterExpr -> { is RegisterExpr -> {
when (index.register) { when (index.register) {

View File

@ -57,8 +57,7 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg
} }
} }
targetMemory!=null -> { targetMemory!=null -> {
val addressExpr = targetMemory.addressExpression when (val addressExpr = targetMemory.addressExpression) {
when (addressExpr) {
is NumericLiteralValue -> { is NumericLiteralValue -> {
val what = addressExpr.number.toHex() val what = addressExpr.number.toHex()
asmgen.out(if(incr) " inc $what" else " dec $what") asmgen.out(if(incr) " inc $what" else " dec $what")

View File

@ -120,8 +120,7 @@ fun builtinFunctionReturnType(function: String, args: List<Expression>, program:
val idt = arglist.inferType(program) val idt = arglist.inferType(program)
if(!idt.isKnown) if(!idt.isKnown)
throw FatalAstException("couldn't determine type of iterable $arglist") throw FatalAstException("couldn't determine type of iterable $arglist")
val dt = idt.typeOrElse(DataType.STRUCT) return when(val dt = idt.typeOrElse(DataType.STRUCT)) {
return when(dt) {
in NumericDatatypes -> dt in NumericDatatypes -> dt
in StringDatatypes -> dt in StringDatatypes -> dt
in ArrayDatatypes -> ArrayElementTypes.getValue(dt) in ArrayDatatypes -> ArrayElementTypes.getValue(dt)

View File

@ -136,7 +136,7 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
// removes 'duplicate' assignments that assign the isSameAs target // removes 'duplicate' assignments that assign the isSameAs target
val linesToRemove = mutableListOf<Int>() val linesToRemove = mutableListOf<Int>()
var previousAssignmentLine: Int? = null var previousAssignmentLine: Int? = null
for (i in 0 until statements.size) { for (i in statements.indices) {
val stmt = statements[i] as? Assignment val stmt = statements[i] as? Assignment
if (stmt != null && stmt.value is NumericLiteralValue) { if (stmt != null && stmt.value is NumericLiteralValue) {
if (previousAssignmentLine == null) { if (previousAssignmentLine == null) {
@ -172,10 +172,10 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
// printing a literal string of just 2 or 1 characters is replaced by directly outputting those characters // printing a literal string of just 2 or 1 characters is replaced by directly outputting those characters
val arg = functionCallStatement.arglist.single() val arg = functionCallStatement.arglist.single()
val stringVar: IdentifierReference? val stringVar: IdentifierReference?
if(arg is AddressOf) { stringVar = if(arg is AddressOf) {
stringVar = arg.identifier arg.identifier
} else { } else {
stringVar = arg as? IdentifierReference arg as? IdentifierReference
} }
if(stringVar!=null) { if(stringVar!=null) {
val vardecl = stringVar.targetVarDecl(program.namespace)!! val vardecl = stringVar.targetVarDecl(program.namespace)!!

View File

@ -42,8 +42,7 @@ class RuntimeValueNumeric(type: DataType, num: Number): RuntimeValueBase(type) {
when (type) { when (type) {
DataType.UBYTE -> { DataType.UBYTE -> {
val inum = num.toInt() val inum = num.toInt()
if (inum !in 0..255) require(inum in 0..255) { "invalid value for ubyte: $inum" }
throw IllegalArgumentException("invalid value for ubyte: $inum")
byteval = inum.toShort() byteval = inum.toShort()
wordval = null wordval = null
floatval = null floatval = null
@ -51,8 +50,7 @@ class RuntimeValueNumeric(type: DataType, num: Number): RuntimeValueBase(type) {
} }
DataType.BYTE -> { DataType.BYTE -> {
val inum = num.toInt() val inum = num.toInt()
if (inum !in -128..127) require(inum in -128..127) { "invalid value for byte: $inum" }
throw IllegalArgumentException("invalid value for byte: $inum")
byteval = inum.toShort() byteval = inum.toShort()
wordval = null wordval = null
floatval = null floatval = null
@ -60,8 +58,7 @@ class RuntimeValueNumeric(type: DataType, num: Number): RuntimeValueBase(type) {
} }
DataType.UWORD -> { DataType.UWORD -> {
val inum = num.toInt() val inum = num.toInt()
if (inum !in 0..65535) require(inum in 0..65535) { "invalid value for uword: $inum" }
throw IllegalArgumentException("invalid value for uword: $inum")
wordval = inum wordval = inum
byteval = null byteval = null
floatval = null floatval = null
@ -69,8 +66,7 @@ class RuntimeValueNumeric(type: DataType, num: Number): RuntimeValueBase(type) {
} }
DataType.WORD -> { DataType.WORD -> {
val inum = num.toInt() val inum = num.toInt()
if (inum !in -32768..32767) require(inum in -32768..32767) { "invalid value for word: $inum" }
throw IllegalArgumentException("invalid value for word: $inum")
wordval = inum wordval = inum
byteval = null byteval = null
floatval = null floatval = null

View File

@ -116,8 +116,6 @@ class RuntimeVariables {
return where[name] ?: throw NoSuchElementException("no such runtime memory-variable: ${scope.name}.$name") return where[name] ?: throw NoSuchElementException("no such runtime memory-variable: ${scope.name}.$name")
} }
fun swap(a1: VarDecl, a2: VarDecl) = swap(a1.definingScope(), a1.name, a2.definingScope(), a2.name)
fun swap(scope1: INameScope, name1: String, scope2: INameScope, name2: String) { fun swap(scope1: INameScope, name1: String, scope2: INameScope, name2: String) {
val v1 = get(scope1, name1) val v1 = get(scope1, name1)
val v2 = get(scope2, name2) val v2 = get(scope2, name2)