mirror of
https://github.com/irmen/prog8.git
synced 2025-02-18 05:30:34 +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 *************/
|
/*********** Everything starts from here, the Program; zero or more modules *************/
|
||||||
|
@ -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()
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
|
@ -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,
|
||||||
|
@ -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) {
|
||||||
|
@ -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")
|
||||||
|
@ -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)
|
||||||
|
@ -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)!!
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user