some code cleanup

This commit is contained in:
Irmen de Jong 2022-06-12 16:15:08 +02:00
parent 93008ff605
commit c6e92ecac4
18 changed files with 51 additions and 135 deletions

View File

@ -53,13 +53,7 @@ enum class DataType {
enum class CpuRegister {
A,
X,
Y;
fun asRegisterOrPair(): RegisterOrPair = when(this) {
A -> RegisterOrPair.A
X -> RegisterOrPair.X
Y -> RegisterOrPair.Y
}
Y
}
enum class RegisterOrPair {
@ -120,7 +114,6 @@ val WordDatatypes = arrayOf(DataType.UWORD, DataType.WORD)
val IntegerDatatypes = arrayOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD)
val NumericDatatypes = arrayOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT)
val SignedDatatypes = arrayOf(DataType.BYTE, DataType.WORD, DataType.FLOAT)
val IntegerArrayDatatypes = arrayOf(DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W)
val ArrayDatatypes = arrayOf(DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F)
val StringlyDatatypes = arrayOf(DataType.STR, DataType.ARRAY_UB, DataType.ARRAY_B, DataType.UWORD)
val IterableDatatypes = arrayOf(

View File

@ -37,7 +37,6 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
val origAstTarget: AssignTarget? = null
)
{
val constMemoryAddress by lazy { memory?.addressExpression?.constValue(program)?.number?.toUInt() ?: 0u}
val constArrayIndexValue by lazy { array?.indexer?.constIndex()?.toUInt() }
val asmVarname: String by lazy {
if (array == null)
@ -122,9 +121,6 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
val expression: Expression? = null
)
{
val constMemoryAddress by lazy { memory?.addressExpression?.constValue(program)?.number?.toUInt() ?: 0u}
val constArrayIndexValue by lazy { array?.indexer?.constIndex()?.toUInt() }
val asmVarname: String
get() = if(array==null)
variableAsmName!!
@ -132,8 +128,6 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
asmgen.asmVariableName(array.arrayvar)
companion object {
fun fromAstSource(indexer: ArrayIndex, program: Program, asmgen: AsmGen): AsmAssignSource = fromAstSource(indexer.indexExpr, program, asmgen)
fun fromAstSource(value: Expression, program: Program, asmgen: AsmGen): AsmAssignSource {
val cv = value.constValue(program)
if(cv!=null)

View File

@ -291,7 +291,7 @@ internal class AssignmentAsmGen(private val program: Program,
assignRegisterByte(assign.target, CpuRegister.A)
}
is PipeExpression -> {
asmgen.translatePipeExpression(value.source, value.segments, value, false, false)
asmgen.translatePipeExpression(value.source, value.segments, value, isStatement = false, pushResultOnEstack = false)
val resultDt = value.inferType(program)
val register =
if(resultDt.isBytes) RegisterOrPair.A
@ -790,7 +790,7 @@ internal class AssignmentAsmGen(private val program: Program,
when(sourceDt) {
DataType.UBYTE -> {
when(targetDt) {
DataType.UBYTE, DataType.BYTE -> {
DataType.BYTE -> {
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
}
DataType.UWORD, DataType.WORD -> {
@ -813,7 +813,7 @@ internal class AssignmentAsmGen(private val program: Program,
}
DataType.BYTE -> {
when(targetDt) {
DataType.UBYTE, DataType.BYTE -> {
DataType.UBYTE -> {
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
}
DataType.UWORD -> {
@ -843,7 +843,7 @@ internal class AssignmentAsmGen(private val program: Program,
DataType.BYTE, DataType.UBYTE -> {
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
}
DataType.WORD, DataType.UWORD -> {
DataType.WORD -> {
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName | lda $sourceAsmVarName+1 | sta $targetAsmVarName+1")
}
DataType.FLOAT -> {
@ -864,7 +864,7 @@ internal class AssignmentAsmGen(private val program: Program,
DataType.BYTE, DataType.UBYTE -> {
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
}
DataType.WORD, DataType.UWORD -> {
DataType.UWORD -> {
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName | lda $sourceAsmVarName+1 | sta $targetAsmVarName+1")
}
DataType.FLOAT -> {
@ -905,7 +905,7 @@ internal class AssignmentAsmGen(private val program: Program,
when(sourceDt) {
DataType.UBYTE -> {
when(targetDt) {
DataType.UBYTE, DataType.BYTE -> {
DataType.BYTE -> {
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName")
}
DataType.UWORD, DataType.WORD -> {
@ -939,7 +939,7 @@ internal class AssignmentAsmGen(private val program: Program,
}
DataType.BYTE -> {
when(targetDt) {
DataType.UBYTE, DataType.BYTE -> {
DataType.UBYTE -> {
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName")
}
DataType.UWORD -> {
@ -986,7 +986,7 @@ internal class AssignmentAsmGen(private val program: Program,
DataType.BYTE, DataType.UBYTE -> {
asmgen.out(" st${regs.toString().lowercase().first()} $targetAsmVarName")
}
DataType.WORD, DataType.UWORD -> {
DataType.WORD -> {
when(regs) {
RegisterOrPair.AX -> asmgen.out(" sta $targetAsmVarName | stx $targetAsmVarName+1")
RegisterOrPair.AY -> asmgen.out(" sta $targetAsmVarName | sty $targetAsmVarName+1")
@ -1014,7 +1014,7 @@ internal class AssignmentAsmGen(private val program: Program,
DataType.BYTE, DataType.UBYTE -> {
asmgen.out(" st${regs.toString().lowercase().first()} $targetAsmVarName")
}
DataType.WORD, DataType.UWORD -> {
DataType.UWORD -> {
when(regs) {
RegisterOrPair.AX -> asmgen.out(" sta $targetAsmVarName | stx $targetAsmVarName+1")
RegisterOrPair.AY -> asmgen.out(" sta $targetAsmVarName | sty $targetAsmVarName+1")

View File

@ -265,18 +265,18 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
}
}
DataType.FLOAT -> {
when(cast.value.type) {
code += when(cast.value.type) {
DataType.UBYTE -> {
code += VmCodeInstruction(Opcode.FFROMUB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
VmCodeInstruction(Opcode.FFROMUB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
}
DataType.BYTE -> {
code += VmCodeInstruction(Opcode.FFROMSB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
VmCodeInstruction(Opcode.FFROMSB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
}
DataType.UWORD -> {
code += VmCodeInstruction(Opcode.FFROMUW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
VmCodeInstruction(Opcode.FFROMUW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
}
DataType.WORD -> {
code += VmCodeInstruction(Opcode.FFROMSW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
VmCodeInstruction(Opcode.FFROMSW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
}
else -> throw AssemblyError("weird cast value type")
}

View File

@ -13,7 +13,7 @@ import kotlin.math.pow
// TODO add more peephole expression optimizations? Investigate what optimizations binaryen has, also see https://egorbo.com/peephole-optimizations.html
class ExpressionSimplifier(private val program: Program, private val errors: IErrorReporter) : AstWalker() {
class ExpressionSimplifier(private val program: Program) : AstWalker() {
private val powersOfTwo = (1..16).map { (2.0).pow(it) }.toSet()
private val negativePowersOfTwo = powersOfTwo.map { -it }.toSet()

View File

@ -60,8 +60,8 @@ fun Program.inlineSubroutines(): Int {
return inliner.applyModifications()
}
fun Program.simplifyExpressions(errors: IErrorReporter) : Int {
val opti = ExpressionSimplifier(this, errors)
fun Program.simplifyExpressions() : Int {
val opti = ExpressionSimplifier(this)
opti.visit(this)
return opti.applyModifications()
}

View File

@ -347,7 +347,7 @@ private fun optimizeAst(program: Program, compilerOptions: CompilationOptions, e
remover.applyModifications()
while (true) {
// keep optimizing expressions and statements until no more steps remain
val optsDone1 = program.simplifyExpressions(errors)
val optsDone1 = program.simplifyExpressions()
val optsDone2 = program.splitBinaryExpressions(compilerOptions)
val optsDone3 = program.optimizeStatements(errors, functions, compTarget)
val optsDone4 = program.inlineSubroutines()

View File

@ -18,7 +18,7 @@ internal class BeforeAsmTypecastCleaner(val program: Program,
override fun after(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> {
// see if we can remove redundant typecasts (outside of expressions)
// such as casting byte<->ubyte, word<->uword or even redundant casts (sourcetype = target type).
// Also the special typecast of a reference type (str, array) to an UWORD will be changed into address-of,
// the special typecast of a reference type (str, array) to an UWORD will be changed into address-of,
// UNLESS it's a str parameter in the containing subroutine - then we remove the typecast altogether
val sourceDt = typecast.expression.inferType(program).getOr(DataType.UNDEFINED)
if (typecast.type in ByteDatatypes && sourceDt in ByteDatatypes

View File

@ -39,7 +39,8 @@ fun Program.getTempVar(dt: DataType, altNames: Boolean=false): Pair<List<String>
// add new temp variable to the ast directly (we can do this here because we're not iterating inside those container blocks)
val decl = VarDecl(
VarDeclType.VAR, VarDeclOrigin.AUTOGENERATED, dt, ZeropageWish.DONTCARE,
null, tmpvarName[1], null, false, false, null, Position.DUMMY)
null, tmpvarName[1], null, isArray = false, sharedWithAsm = false, subroutineParameter = null, position = Position.DUMMY
)
block.statements.add(decl)
decl.linkParents(block)
return Pair(tmpvarName, decl)

View File

@ -120,8 +120,6 @@ class Program(val name: String,
s.removeStrings(modules)
}
fun sortModules() = _modules.sortBy { it.isLibrary }
private class StringSearch(val program: Program): IAstVisitor {
val removals = mutableListOf<List<String>>()
override fun visit(identifier: IdentifierReference) {

View File

@ -489,9 +489,6 @@ private fun Prog8ANTLRParser.ArrayindexedContext.toAst(): ArrayIndexedExpression
private fun Prog8ANTLRParser.Expression_listContext.toAst() = expression().map{ it.toAst() }
private fun Prog8ANTLRParser.IdentifierContext.toAst() : IdentifierReference =
IdentifierReference(listOf(text), toPosition())
private fun Prog8ANTLRParser.Scoped_identifierContext.toAst() : IdentifierReference =
IdentifierReference(NAME().map { it.text }, toPosition())

View File

@ -188,12 +188,11 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
fun dynamicBooleanType(): InferredTypes.InferredType {
// as a special case, an expression yielding a boolean result, adapts the result
// type to what is required (byte or word), to avoid useless type casting
return if(parent is TypecastExpression)
InferredTypes.InferredType.known((parent as TypecastExpression).type)
else if(parent is Assignment)
(parent as Assignment).target.inferType(program)
else
InferredTypes.InferredType.known(DataType.UBYTE)
return when (parent) {
is TypecastExpression -> InferredTypes.InferredType.known((parent as TypecastExpression).type)
is Assignment -> (parent as Assignment).target.inferType(program)
else -> InferredTypes.InferredType.known(DataType.UBYTE)
}
}
return when (operator) {

View File

@ -650,7 +650,7 @@ class InlineAssembly(val assembly: String, override val position: Position) : St
val names: Set<String> by lazy {
// A cache of all the words (identifiers) present in this block of assembly code
// this is used when checking if prog8 names are referenced from assembly code
val wordPattern = Regex("""\b([_a-zA-Z][_a-zA-Z0-9]+?)\b""")
val wordPattern = Regex("""\b([_a-zA-Z]\w+?)\b""")
assembly.splitToSequence('\n')
.map {
val everythintBeforeComment = it.substringBefore(';')
@ -1095,7 +1095,7 @@ class Pipe(override var source: Expression,
// Calls to builtin functions will be replaced with this node just before handing the Ast to the codegen.
// this is meant to eventually (?) be able to not have any FunctionCallStatement nodes to worry about anymore
// in the codegen, because they have been converted into GoSub (for instance) or this node.
// However, if/when the codegen is moved over to use the new CodeAst (PtProgram etc etc) this is all moot.
// However, if/when the codegen is moved over to use the new CodeAst (PtProgram etc. etc.) this is all moot.
class BuiltinFunctionCallStatement(override var target: IdentifierReference,
override var args: MutableList<Expression>,
override val position: Position) : Statement(), IFunctionCall {

View File

@ -8,7 +8,6 @@ import prog8.ast.expressions.*
import prog8.ast.statements.VarDecl
import prog8.code.core.*
import kotlin.math.abs
import kotlin.math.floor
import kotlin.math.sign
import kotlin.math.sqrt
@ -149,21 +148,6 @@ class NotConstArgumentException: AstException("not a const argument to a built-i
class CannotEvaluateException(func:String, msg: String): FatalAstException("cannot evaluate built-in function $func: $msg")
private fun oneDoubleArg(args: List<Expression>, position: Position, program: Program, function: (arg: Double)->Number): NumericLiteral {
if(args.size!=1)
throw SyntaxError("built-in function requires one floating point argument", position)
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
val float = constval.number
return numericLiteral(function(float), args[0].position)
}
private fun oneDoubleArgOutputWord(args: List<Expression>, position: Position, program: Program, function: (arg: Double)->Double): NumericLiteral {
if(args.size!=1)
throw SyntaxError("built-in function requires one floating point argument", position)
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
return NumericLiteral(DataType.WORD, function(constval.number), args[0].position)
}
private fun oneIntArgOutputInt(args: List<Expression>, position: Position, program: Program, function: (arg: Int)->Double): NumericLiteral {
if(args.size!=1)
throw SyntaxError("built-in function requires one integer argument", position)
@ -172,7 +156,7 @@ private fun oneIntArgOutputInt(args: List<Expression>, position: Position, progr
throw SyntaxError("built-in function requires one integer argument", position)
val integer = constval.number.toInt()
return numericLiteral(function(integer).toInt(), args[0].position)
return NumericLiteral.optimalInteger(function(integer).toInt(), args[0].position)
}
private fun collectionArg(args: List<Expression>, position: Position, program: Program, function: (arg: List<Double>)->Double): NumericLiteral {
@ -194,7 +178,7 @@ private fun builtinAbs(args: List<Expression>, position: Position, program: Prog
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
return when (constval.type) {
in IntegerDatatypes -> numericLiteral(abs(constval.number.toInt()), args[0].position)
in IntegerDatatypes -> NumericLiteral.optimalInteger(abs(constval.number.toInt()), args[0].position)
else -> throw SyntaxError("abs requires one integer argument", position)
}
}
@ -215,7 +199,7 @@ private fun builtinSizeof(args: List<Expression>, position: Position, program: P
dt.isArray -> {
val length = (target as VarDecl).arraysize!!.constIndex() ?: throw CannotEvaluateException("sizeof", "unknown array size")
val elementDt = ArrayToElementTypes.getValue(dt.getOr(DataType.UNDEFINED))
numericLiteral(program.memsizer.memorySize(elementDt) * length, position)
NumericLiteral.optimalInteger(program.memsizer.memorySize(elementDt) * length, position)
}
dt istype DataType.STR -> throw SyntaxError("sizeof str is undefined, did you mean len?", position)
else -> NumericLiteral(DataType.UBYTE, program.memsizer.memorySize(dt.getOr(DataType.UNDEFINED)).toDouble(), position)
@ -272,21 +256,3 @@ private fun builtinSgn(args: List<Expression>, position: Position, program: Prog
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
return NumericLiteral(DataType.BYTE, constval.number.sign, position)
}
private fun numericLiteral(value: Number, position: Position): NumericLiteral {
val floatNum=value.toDouble()
val tweakedValue: Number =
if(floatNum== floor(floatNum) && (floatNum>=-32768 && floatNum<=65535))
floatNum.toInt() // we have an integer disguised as a float.
else
floatNum
return when(tweakedValue) {
is Int -> NumericLiteral.optimalInteger(value.toInt(), position)
is Short -> NumericLiteral.optimalInteger(value.toInt(), position)
is Byte -> NumericLiteral(DataType.UBYTE, value.toDouble(), position)
is Double -> NumericLiteral(DataType.FLOAT, value.toDouble(), position)
is Float -> NumericLiteral(DataType.FLOAT, value.toDouble(), position)
else -> throw FatalAstException("invalid number type ${value::class}")
}
}

View File

@ -4,27 +4,6 @@
; NOTE: meant to test to virtual machine output target (use -target vitual)
other {
ubyte variable = 40
ubyte var2=2
sub func1(ubyte arg) -> ubyte {
txt.print_ub(arg)
txt.spc()
return arg*var2
}
sub inliner() -> ubyte {
return func1(variable)
}
sub inliner2() {
txt.print_ub(22)
return
}
}
main {
; sub ands(ubyte arg, ubyte b1, ubyte b2, ubyte b3, ubyte b4) -> ubyte {
@ -53,34 +32,23 @@ main {
sub start() {
; mcCarthy()
other.inliner2()
other.inliner2()
rnd()
void other.inliner()
void other.inliner()
ubyte derp = other.inliner() * other.inliner() ; TODO inline this (was $207 bytes size)
txt.print_ub(derp)
txt.nl()
; a "pixelshader":
sys.gfx_enable(0) ; enable lo res screen
ubyte shifter
; ; a "pixelshader":
; sys.gfx_enable(0) ; enable lo res screen
; ubyte shifter
;
; repeat {
; uword xx
; uword yy = 0
; repeat 240 {
; xx = 0
; repeat 320 {
; sys.gfx_plot(xx, yy, xx*yy + shifter as ubyte)
; xx++
; }
; yy++
; }
; shifter+=4
; }
repeat {
uword xx
uword yy = 0
repeat 240 {
xx = 0
repeat 320 {
sys.gfx_plot(xx, yy, xx*yy + shifter as ubyte)
xx++
}
yy++
}
shifter+=4
}
}
}

View File

@ -65,7 +65,7 @@ class Assembler {
placeholders.clear()
val program = mutableListOf<Instruction>()
val instructionPattern = Regex("""([a-z]+)(\.b|\.w|\.f)?(.*)""", RegexOption.IGNORE_CASE)
val labelPattern = Regex("""_([a-z0-9\._]+):""")
val labelPattern = Regex("""_([a-z\d\._]+):""")
for (line in source.lines()) {
if(line.isBlank() || line.startsWith(';'))
continue

View File

@ -6,7 +6,7 @@ package prog8.vm
*/
class Registers {
private val registers = Array<UShort>(65536) { 0u }
private val floatRegisters = Array<Float>(65535) { 0f }
private val floatRegisters = Array(65535) { 0f }
fun reset() {
registers.fill(0u)

View File

@ -1785,7 +1785,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
}
// probably called via reflection
class VmRunner(): IVirtualMachineRunner {
class VmRunner: IVirtualMachineRunner {
override fun runProgram(source: String, throttle: Boolean) {
val (memsrc, programsrc) = source.split("------PROGRAM------".toRegex(), 2)
val memory = Memory()