mirror of
https://github.com/irmen/prog8.git
synced 2024-11-25 19:31:36 +00:00
code cleanups
This commit is contained in:
parent
b79af624ae
commit
2d768c3f28
@ -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 *************/
|
||||
|
@ -1,12 +1,12 @@
|
||||
package prog8.ast.expressions
|
||||
|
||||
import prog8.ast.base.DataType
|
||||
import java.util.*
|
||||
|
||||
object InferredTypes {
|
||||
class InferredType private constructor(val isUnknown: Boolean, val isVoid: Boolean, private var datatype: DataType?) {
|
||||
init {
|
||||
if(datatype!=null && (isUnknown || isVoid))
|
||||
throw IllegalArgumentException("invalid combination of args")
|
||||
require(!(datatype!=null && (isUnknown || isVoid))) { "invalid combination of args" }
|
||||
}
|
||||
|
||||
val isKnown = datatype!=null
|
||||
@ -32,6 +32,8 @@ object InferredTypes {
|
||||
else -> "<unknown>"
|
||||
}
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = Objects.hash(isVoid, datatype)
|
||||
}
|
||||
|
||||
private val unknownInstance = InferredType.unknown()
|
||||
|
@ -1,3 +1,5 @@
|
||||
@file:Suppress("DuplicatedCode")
|
||||
|
||||
package prog8.ast.processing
|
||||
|
||||
import prog8.ast.IFunctionCall
|
||||
@ -945,9 +947,8 @@ internal class AstChecker(private val program: Program,
|
||||
if(dt !in NumericDatatypes && dt !in ArrayDatatypes)
|
||||
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)
|
||||
}
|
||||
|
||||
@ -1231,11 +1232,11 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
val array = value.value.map {
|
||||
if(it is NumericLiteralValue)
|
||||
it.number.toInt()
|
||||
else if(it is AddressOf)
|
||||
it.identifier.heapId(program.namespace)
|
||||
else -9999999
|
||||
when (it) {
|
||||
is NumericLiteralValue -> it.number.toInt()
|
||||
is AddressOf -> it.identifier.heapId(program.namespace)
|
||||
else -> -9999999
|
||||
}
|
||||
}
|
||||
val correct: Boolean
|
||||
when (type) {
|
||||
|
@ -219,15 +219,8 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
||||
val subroutine = returnStmt.definingSubroutine()!!
|
||||
if(subroutine.returntypes.size!=1)
|
||||
return returnStmt // mismatch in number of return values, error will be printed later.
|
||||
val newValue: Expression
|
||||
val lval = returnStmt.value as? NumericLiteralValue
|
||||
if(lval!=null) {
|
||||
newValue = lval.cast(subroutine.returntypes.single())
|
||||
} else {
|
||||
newValue = returnStmt.value!!
|
||||
}
|
||||
|
||||
returnStmt.value = newValue
|
||||
returnStmt.value = lval?.cast(subroutine.returntypes.single()) ?: returnStmt.value!!
|
||||
}
|
||||
return super.visit(returnStmt)
|
||||
}
|
||||
@ -236,18 +229,19 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
||||
val array = super.visit(arrayLiteral)
|
||||
if(array is ArrayLiteralValue) {
|
||||
val vardecl = array.parent as? VarDecl
|
||||
return if (vardecl!=null) {
|
||||
fixupArrayDatatype(array, vardecl, program)
|
||||
} else if(array.heapId!=null) {
|
||||
// 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)
|
||||
val datatype = determineArrayDt(array.value)
|
||||
val litval2 = array.cast(datatype)!!
|
||||
litval2.parent = array.parent
|
||||
// finally, replace the literal array by a identifier reference.
|
||||
makeIdentifierFromRefLv(litval2)
|
||||
} else
|
||||
array
|
||||
return when {
|
||||
vardecl!=null -> fixupArrayDatatype(array, vardecl, program)
|
||||
array.heapId!=null -> {
|
||||
// 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)
|
||||
val datatype = determineArrayDt(array.value)
|
||||
val litval2 = array.cast(datatype)!!
|
||||
litval2.parent = array.parent
|
||||
// finally, replace the literal array by a identifier reference.
|
||||
makeIdentifierFromRefLv(litval2)
|
||||
}
|
||||
else -> array
|
||||
}
|
||||
}
|
||||
return array
|
||||
}
|
||||
@ -272,8 +266,7 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
||||
|
||||
private fun determineArrayDt(array: Array<Expression>): DataType {
|
||||
val datatypesInArray = array.map { it.inferType(program) }
|
||||
if(datatypesInArray.isEmpty() || datatypesInArray.any { !it.isKnown })
|
||||
throw IllegalArgumentException("can't determine type of empty array")
|
||||
require(datatypesInArray.isNotEmpty() && datatypesInArray.all { it.isKnown }) { "can't determine type of empty array" }
|
||||
val dts = datatypesInArray.map { it.typeOrElse(DataType.STRUCT) }
|
||||
return when {
|
||||
DataType.FLOAT in dts -> DataType.ARRAY_F
|
||||
|
@ -142,8 +142,7 @@ interface IAstModifyingVisitor {
|
||||
}
|
||||
|
||||
fun visit(forLoop: ForLoop): Statement {
|
||||
val newloopvar = forLoop.loopVar?.accept(this)
|
||||
when(newloopvar) {
|
||||
when(val newloopvar = forLoop.loopVar?.accept(this)) {
|
||||
is IdentifierReference -> forLoop.loopVar = newloopvar
|
||||
null -> forLoop.loopVar = null
|
||||
else -> throw FatalAstException("can't change class of loopvar")
|
||||
@ -179,8 +178,7 @@ interface IAstModifyingVisitor {
|
||||
}
|
||||
|
||||
fun visit(assignTarget: AssignTarget): AssignTarget {
|
||||
val ident = assignTarget.identifier?.accept(this)
|
||||
when (ident) {
|
||||
when (val ident = assignTarget.identifier?.accept(this)) {
|
||||
is IdentifierReference -> assignTarget.identifier = ident
|
||||
null -> assignTarget.identifier = null
|
||||
else -> throw FatalAstException("can't change class of assign target identifier")
|
||||
|
@ -1,6 +1,5 @@
|
||||
package prog8.compiler
|
||||
|
||||
import prog8.ast.expressions.AddressOf
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.nio.file.Path
|
||||
@ -24,8 +23,6 @@ enum class ZeropageType {
|
||||
DONTUSE
|
||||
}
|
||||
|
||||
data class IntegerOrAddressOf(val integer: Int?, val addressOf: AddressOf?)
|
||||
|
||||
data class CompilationOptions(val output: OutputType,
|
||||
val launcher: LauncherType,
|
||||
val zeropage: ZeropageType,
|
||||
|
@ -820,8 +820,7 @@ internal class AsmGen(val program: Program,
|
||||
}
|
||||
|
||||
internal fun translateArrayIndexIntoA(expr: ArrayIndexedExpression) {
|
||||
val index = expr.arrayspec.index
|
||||
when (index) {
|
||||
when (val index = expr.arrayspec.index) {
|
||||
is NumericLiteralValue -> throw AssemblyError("this should be optimized directly")
|
||||
is RegisterExpr -> {
|
||||
when (index.register) {
|
||||
|
@ -57,8 +57,7 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg
|
||||
}
|
||||
}
|
||||
targetMemory!=null -> {
|
||||
val addressExpr = targetMemory.addressExpression
|
||||
when (addressExpr) {
|
||||
when (val addressExpr = targetMemory.addressExpression) {
|
||||
is NumericLiteralValue -> {
|
||||
val what = addressExpr.number.toHex()
|
||||
asmgen.out(if(incr) " inc $what" else " dec $what")
|
||||
|
@ -120,8 +120,7 @@ fun builtinFunctionReturnType(function: String, args: List<Expression>, program:
|
||||
val idt = arglist.inferType(program)
|
||||
if(!idt.isKnown)
|
||||
throw FatalAstException("couldn't determine type of iterable $arglist")
|
||||
val dt = idt.typeOrElse(DataType.STRUCT)
|
||||
return when(dt) {
|
||||
return when(val dt = idt.typeOrElse(DataType.STRUCT)) {
|
||||
in NumericDatatypes -> dt
|
||||
in StringDatatypes -> dt
|
||||
in ArrayDatatypes -> ArrayElementTypes.getValue(dt)
|
||||
|
@ -136,7 +136,7 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
|
||||
// removes 'duplicate' assignments that assign the isSameAs target
|
||||
val linesToRemove = mutableListOf<Int>()
|
||||
var previousAssignmentLine: Int? = null
|
||||
for (i in 0 until statements.size) {
|
||||
for (i in statements.indices) {
|
||||
val stmt = statements[i] as? Assignment
|
||||
if (stmt != null && stmt.value is NumericLiteralValue) {
|
||||
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
|
||||
val arg = functionCallStatement.arglist.single()
|
||||
val stringVar: IdentifierReference?
|
||||
if(arg is AddressOf) {
|
||||
stringVar = arg.identifier
|
||||
stringVar = if(arg is AddressOf) {
|
||||
arg.identifier
|
||||
} else {
|
||||
stringVar = arg as? IdentifierReference
|
||||
arg as? IdentifierReference
|
||||
}
|
||||
if(stringVar!=null) {
|
||||
val vardecl = stringVar.targetVarDecl(program.namespace)!!
|
||||
|
@ -42,8 +42,7 @@ class RuntimeValueNumeric(type: DataType, num: Number): RuntimeValueBase(type) {
|
||||
when (type) {
|
||||
DataType.UBYTE -> {
|
||||
val inum = num.toInt()
|
||||
if (inum !in 0..255)
|
||||
throw IllegalArgumentException("invalid value for ubyte: $inum")
|
||||
require(inum in 0..255) { "invalid value for ubyte: $inum" }
|
||||
byteval = inum.toShort()
|
||||
wordval = null
|
||||
floatval = null
|
||||
@ -51,8 +50,7 @@ class RuntimeValueNumeric(type: DataType, num: Number): RuntimeValueBase(type) {
|
||||
}
|
||||
DataType.BYTE -> {
|
||||
val inum = num.toInt()
|
||||
if (inum !in -128..127)
|
||||
throw IllegalArgumentException("invalid value for byte: $inum")
|
||||
require(inum in -128..127) { "invalid value for byte: $inum" }
|
||||
byteval = inum.toShort()
|
||||
wordval = null
|
||||
floatval = null
|
||||
@ -60,8 +58,7 @@ class RuntimeValueNumeric(type: DataType, num: Number): RuntimeValueBase(type) {
|
||||
}
|
||||
DataType.UWORD -> {
|
||||
val inum = num.toInt()
|
||||
if (inum !in 0..65535)
|
||||
throw IllegalArgumentException("invalid value for uword: $inum")
|
||||
require(inum in 0..65535) { "invalid value for uword: $inum" }
|
||||
wordval = inum
|
||||
byteval = null
|
||||
floatval = null
|
||||
@ -69,8 +66,7 @@ class RuntimeValueNumeric(type: DataType, num: Number): RuntimeValueBase(type) {
|
||||
}
|
||||
DataType.WORD -> {
|
||||
val inum = num.toInt()
|
||||
if (inum !in -32768..32767)
|
||||
throw IllegalArgumentException("invalid value for word: $inum")
|
||||
require(inum in -32768..32767) { "invalid value for word: $inum" }
|
||||
wordval = inum
|
||||
byteval = null
|
||||
floatval = null
|
||||
|
@ -116,8 +116,6 @@ class RuntimeVariables {
|
||||
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) {
|
||||
val v1 = get(scope1, name1)
|
||||
val v2 = get(scope2, name2)
|
||||
|
Loading…
Reference in New Issue
Block a user