mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
replace unwritten vars by consts. Improved const eval.
Fixed some slight bugs in library code
This commit is contained in:
parent
b428343c2a
commit
09c6cb4d6b
@ -3,10 +3,8 @@ package prog8.code.core
|
||||
val AssociativeOperators = setOf("+", "*", "&", "|", "^", "==", "!=")
|
||||
val ComparisonOperators = setOf("==", "!=", "<", ">", "<=", ">=")
|
||||
val LogicalOperators = setOf("and", "or", "xor", "not")
|
||||
val AugmentAssignmentOperators = setOf("+", "-", "/", "*", "&", "|", "^", "<<", ">>", "%", "and", "or", "xor")
|
||||
val BitwiseOperators = setOf("&", "|", "^", "~")
|
||||
val PrefixOperators = setOf("+", "-", "~", "not")
|
||||
// val InvalidOperatorsForBoolean = setOf("+", "-", "*", "/", "%", "<<", ">>") + BitwiseOperators
|
||||
|
||||
fun invertedComparisonOperator(operator: String) =
|
||||
when (operator) {
|
||||
|
@ -19,9 +19,9 @@ class ConstExprEvaluator {
|
||||
"*" -> multiply(left, right)
|
||||
"/" -> divide(left, right)
|
||||
"%" -> remainder(left, right)
|
||||
"&" -> bitwiseand(left, right)
|
||||
"|" -> bitwiseor(left, right)
|
||||
"^" -> bitwisexor(left, right)
|
||||
"&" -> bitwiseAnd(left, right)
|
||||
"|" -> bitwiseOr(left, right)
|
||||
"^" -> bitwiseXor(left, right)
|
||||
"<" -> NumericLiteral.fromBoolean(left < right, left.position)
|
||||
">" -> NumericLiteral.fromBoolean(left > right, left.position)
|
||||
"<=" -> NumericLiteral.fromBoolean(left <= right, left.position)
|
||||
@ -30,6 +30,9 @@ class ConstExprEvaluator {
|
||||
"!=" -> NumericLiteral.fromBoolean(left != right, left.position)
|
||||
"<<" -> shiftedleft(left, right)
|
||||
">>" -> shiftedright(left, right)
|
||||
"and" -> logicalAnd(left, right)
|
||||
"or" -> logicalOr(left, right)
|
||||
"xor" -> logicalXor(left, right)
|
||||
else -> throw FatalAstException("const evaluation for invalid operator $operator")
|
||||
}
|
||||
} catch (ax: FatalAstException) {
|
||||
@ -55,7 +58,7 @@ class ConstExprEvaluator {
|
||||
return NumericLiteral(left.type, result.toDouble(), left.position)
|
||||
}
|
||||
|
||||
private fun bitwisexor(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
|
||||
private fun bitwiseXor(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
|
||||
if(left.type== DataType.UBYTE) {
|
||||
if(right.type in IntegerDatatypes) {
|
||||
return NumericLiteral(DataType.UBYTE, (left.number.toInt() xor (right.number.toInt() and 255)).toDouble(), left.position)
|
||||
@ -68,7 +71,7 @@ class ConstExprEvaluator {
|
||||
throw ExpressionError("cannot calculate $left ^ $right", left.position)
|
||||
}
|
||||
|
||||
private fun bitwiseor(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
|
||||
private fun bitwiseOr(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
|
||||
if(left.type== DataType.UBYTE) {
|
||||
if(right.type in IntegerDatatypes) {
|
||||
return NumericLiteral(DataType.UBYTE, (left.number.toInt() or (right.number.toInt() and 255)).toDouble(), left.position)
|
||||
@ -81,7 +84,7 @@ class ConstExprEvaluator {
|
||||
throw ExpressionError("cannot calculate $left | $right", left.position)
|
||||
}
|
||||
|
||||
private fun bitwiseand(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
|
||||
private fun bitwiseAnd(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
|
||||
if(left.type== DataType.UBYTE) {
|
||||
if(right.type in IntegerDatatypes) {
|
||||
return NumericLiteral(DataType.UBYTE, (left.number.toInt() and (right.number.toInt() and 255)).toDouble(), left.position)
|
||||
@ -94,6 +97,15 @@ class ConstExprEvaluator {
|
||||
throw ExpressionError("cannot calculate $left & $right", left.position)
|
||||
}
|
||||
|
||||
private fun logicalAnd(left: NumericLiteral, right: NumericLiteral): NumericLiteral =
|
||||
NumericLiteral.fromBoolean(left.asBooleanValue and right.asBooleanValue, left.position)
|
||||
|
||||
private fun logicalOr(left: NumericLiteral, right: NumericLiteral): NumericLiteral =
|
||||
NumericLiteral.fromBoolean(left.asBooleanValue or right.asBooleanValue, left.position)
|
||||
|
||||
private fun logicalXor(left: NumericLiteral, right: NumericLiteral): NumericLiteral =
|
||||
NumericLiteral.fromBoolean(left.asBooleanValue xor right.asBooleanValue, left.position)
|
||||
|
||||
private fun plus(left: NumericLiteral, right: NumericLiteral): NumericLiteral {
|
||||
val error = "cannot add $left and $right"
|
||||
return when (left.type) {
|
||||
|
@ -18,6 +18,8 @@ import kotlin.math.floor
|
||||
|
||||
class ConstantFoldingOptimizer(private val program: Program, private val errors: IErrorReporter) : AstWalker() {
|
||||
|
||||
private val evaluator = ConstExprEvaluator()
|
||||
|
||||
override fun before(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> {
|
||||
// @( &thing ) --> thing (but only if thing is a byte type!)
|
||||
val addrOf = memread.addressExpression as? AddressOf
|
||||
@ -137,12 +139,13 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors:
|
||||
}
|
||||
}
|
||||
|
||||
val evaluator = ConstExprEvaluator()
|
||||
|
||||
// const fold when both operands are a const
|
||||
// const fold when both operands are a const.
|
||||
// if in a chained comparison, that one has to be desugared first though.
|
||||
if(leftconst != null && rightconst != null) {
|
||||
val result = evaluator.evaluate(leftconst, expr.operator, rightconst)
|
||||
modifications += IAstModification.ReplaceNode(expr, result, parent)
|
||||
if((expr.parent as? BinaryExpression)?.isChainedComparison()!=true) {
|
||||
val result = evaluator.evaluate(leftconst, expr.operator, rightconst)
|
||||
modifications += IAstModification.ReplaceNode(expr, result, parent)
|
||||
}
|
||||
}
|
||||
|
||||
if(leftconst==null && rightconst!=null && rightconst.number<0.0) {
|
||||
|
@ -1,17 +1,11 @@
|
||||
package prog8.optimizer
|
||||
|
||||
import prog8.ast.*
|
||||
import prog8.ast.expressions.BinaryExpression
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.expressions.PrefixExpression
|
||||
import prog8.ast.expressions.TypecastExpression
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.ICompilationTarget
|
||||
import prog8.code.core.IErrorReporter
|
||||
import prog8.code.core.internedStringsModuleName
|
||||
import prog8.code.core.*
|
||||
import prog8.compiler.CallGraph
|
||||
|
||||
|
||||
@ -124,6 +118,36 @@ class UnusedCodeRemover(private val program: Program,
|
||||
return listOf(IAstModification.Remove(decl, parent as IStatementContainer))
|
||||
}
|
||||
else {
|
||||
val (writes, reads) = usages
|
||||
.partition{
|
||||
it is InlineAssembly // can't really tell if it's written to or only read, assume the worst
|
||||
|| it.parent is AssignTarget
|
||||
|| it.parent is ForLoop
|
||||
|| it.parent is AddressOf
|
||||
|| (it.parent as? IFunctionCall)?.target?.nameInSource?.singleOrNull() in InplaceModifyingBuiltinFunctions
|
||||
}
|
||||
val singleAssignment = writes.singleOrNull()?.parent?.parent as? Assignment ?: writes.singleOrNull()?.parent as? Assignment
|
||||
if (singleAssignment!=null && reads.isNotEmpty()) {
|
||||
if (singleAssignment.origin == AssignmentOrigin.VARINIT && singleAssignment.value.constValue(program) != null) {
|
||||
// variable only has a single write and it is the initialization value, so it can be replaced with a constant, IF the value is a constant
|
||||
errors.warn("variable is never written to and was replaced by a constant", decl.position)
|
||||
val const = VarDecl(VarDeclType.CONST, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, decl.names, singleAssignment.value, decl.sharedWithAsm, decl.splitArray, decl.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(decl, const, parent),
|
||||
IAstModification.Remove(singleAssignment, singleAssignment.parent as IStatementContainer)
|
||||
)
|
||||
}
|
||||
}
|
||||
/*
|
||||
TODO: need to check if there are no variable usages between the declaration and the assignment (because these rely on the original initialization value)
|
||||
if(writes.size==2) {
|
||||
val firstAssignment = writes[0].parent as? Assignment
|
||||
val secondAssignment = writes[1].parent as? Assignment
|
||||
if(firstAssignment?.origin==AssignmentOrigin.VARINIT && secondAssignment?.value?.constValue(program)!=null) {
|
||||
errors.warn("variable is only assigned once here, consider using this as the initialization value in the declaration instead", secondAssignment.position)
|
||||
}
|
||||
}
|
||||
*/
|
||||
if(usages.size==1) {
|
||||
val singleUse = usages[0].parent
|
||||
if(singleUse is AssignTarget) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
; BMX Specification: https://cx16forum.com/forum/viewtopic.php?t=6945
|
||||
|
||||
%import diskio
|
||||
%option no_symbol_prefixing, ignore_unused
|
||||
|
||||
bmx {
|
||||
|
||||
@ -17,7 +18,7 @@ bmx {
|
||||
uword palette_entries ; 1-256
|
||||
ubyte palette_start
|
||||
ubyte compression
|
||||
uword palette_buffer_ptr = 0 ; should you want to load or save the palette into main memory instead of directly into vram
|
||||
uword @shared palette_buffer_ptr = 0 ; should you want to load or save the palette into main memory instead of directly into vram
|
||||
|
||||
uword error_message ; pointer to error message, or 0 if all ok
|
||||
ubyte old_drivenumber
|
||||
|
@ -22,7 +22,7 @@ diskio {
|
||||
const ubyte READ_IO_CHANNEL=12
|
||||
const ubyte WRITE_IO_CHANNEL=13
|
||||
|
||||
ubyte drivenumber = 8 ; user programs can set this to the drive number they want to load/save to!
|
||||
ubyte @shared drivenumber = 8 ; user programs can set this to the drive number they want to load/save to!
|
||||
|
||||
sub reset_read_channel() {
|
||||
void cbm.CHKIN(READ_IO_CHANNEL)
|
||||
|
@ -11,7 +11,7 @@ diskio {
|
||||
const ubyte READ_IO_CHANNEL=12
|
||||
const ubyte WRITE_IO_CHANNEL=13
|
||||
|
||||
ubyte drivenumber = 8 ; user programs can set this to the drive number they want to load/save to!
|
||||
ubyte @shared drivenumber = 8 ; user programs can set this to the drive number they want to load/save to!
|
||||
|
||||
sub reset_read_channel() {
|
||||
void cbm.CHKIN(READ_IO_CHANNEL)
|
||||
|
@ -81,8 +81,7 @@ internal class BeforeAsmTypecastCleaner(val program: Program,
|
||||
// also convert calls to builtin functions to BuiltinFunctionCall nodes to make things easier for codegen
|
||||
|
||||
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> {
|
||||
if(functionCallStatement.target.nameInSource.size==1
|
||||
&& functionCallStatement.target.nameInSource[0] in program.builtinFunctions.names) {
|
||||
if(functionCallStatement.target.nameInSource.singleOrNull() in program.builtinFunctions.names) {
|
||||
return listOf(IAstModification.ReplaceNode(
|
||||
functionCallStatement,
|
||||
BuiltinFunctionCallStatement(functionCallStatement.target, functionCallStatement.args, functionCallStatement.position),
|
||||
@ -94,8 +93,7 @@ internal class BeforeAsmTypecastCleaner(val program: Program,
|
||||
}
|
||||
|
||||
override fun before(functionCallExpr: FunctionCallExpression, parent: Node): Iterable<IAstModification> {
|
||||
if(functionCallExpr.target.nameInSource.size==1
|
||||
&& functionCallExpr.target.nameInSource[0] in program.builtinFunctions.names) {
|
||||
if(functionCallExpr.target.nameInSource.singleOrNull() in program.builtinFunctions.names) {
|
||||
return listOf(IAstModification.ReplaceNode(
|
||||
functionCallExpr,
|
||||
BuiltinFunctionCall(functionCallExpr.target, functionCallExpr.args, functionCallExpr.position),
|
||||
|
@ -262,10 +262,9 @@ _after:
|
||||
|
||||
// desugar chained comparisons: i < x < j ---> i<x and x<j
|
||||
// only if i<x or x<j was not written in parentheses! (i<x) < y, i < (x<y) -> leave untouched
|
||||
if(expr.operator in ComparisonOperators) {
|
||||
if(expr.isChainedComparison()) {
|
||||
val leftBinExpr = expr.left as? BinaryExpression
|
||||
val rightBinExpr = expr.right as? BinaryExpression
|
||||
if(leftBinExpr!=null && !leftBinExpr.insideParentheses && leftBinExpr.operator in ComparisonOperators) {
|
||||
if(leftBinExpr!=null) {
|
||||
if(!leftBinExpr.right.isSimple) {
|
||||
errors.warn("possible multiple evaluation of subexpression in chained comparison, consider using a temporary variable", leftBinExpr.right.position)
|
||||
}
|
||||
@ -273,7 +272,8 @@ _after:
|
||||
val desugar = BinaryExpression(leftBinExpr, "and", right, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, desugar, parent))
|
||||
}
|
||||
else if(rightBinExpr!=null && !rightBinExpr.insideParentheses && rightBinExpr.operator in ComparisonOperators) {
|
||||
val rightBinExpr = expr.right as? BinaryExpression
|
||||
if(rightBinExpr!=null) {
|
||||
if(!rightBinExpr.left.isSimple) {
|
||||
errors.warn("possible multiple evaluation of subexpression in chained comparison, consider using a temporary variable", rightBinExpr.left.position)
|
||||
}
|
||||
|
@ -106,8 +106,8 @@ class TestOptimization: FunSpec({
|
||||
const ubyte boardOffsetC = 3
|
||||
|
||||
sub start() {
|
||||
uword load_location = 12345
|
||||
word llw = 12345
|
||||
uword @shared load_location = 12345
|
||||
word @shared llw = 12345
|
||||
cx16.r0 = load_location + 8000 + 1000 + 1000
|
||||
cx16.r2 = 8000 + 1000 + 1000 + load_location
|
||||
cx16.r4 = load_location + boardOffsetC + boardHeightC - 1
|
||||
@ -156,8 +156,8 @@ class TestOptimization: FunSpec({
|
||||
%option enable_floats
|
||||
main {
|
||||
sub start() {
|
||||
float llw = 300.0
|
||||
float result
|
||||
float @shared llw = 300.0
|
||||
float @shared result
|
||||
result = 9 * 2 * 10 * llw
|
||||
result++
|
||||
result = llw * 9 * 2 * 10
|
||||
@ -214,7 +214,7 @@ class TestOptimization: FunSpec({
|
||||
val source = """
|
||||
main {
|
||||
sub start() {
|
||||
word llw = 300
|
||||
word @shared llw = 300
|
||||
cx16.r0s = 9 * 2 * 10 * llw
|
||||
cx16.r1s = llw * 9 * 2 * 10
|
||||
cx16.r2s = llw / 30 / 3
|
||||
@ -483,8 +483,8 @@ class TestOptimization: FunSpec({
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
uword aa
|
||||
ubyte zz
|
||||
uword @shared aa
|
||||
ubyte @shared zz
|
||||
@(aa) = zz + 32 ; do not optimize this away!
|
||||
}
|
||||
}
|
||||
@ -633,8 +633,8 @@ class TestOptimization: FunSpec({
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
ubyte source=99
|
||||
ubyte thingy=42
|
||||
ubyte @shared source=99
|
||||
ubyte @shared thingy=42
|
||||
|
||||
if source==3 or source==4 or source==99 or source==1
|
||||
thingy++
|
||||
@ -673,8 +673,8 @@ class TestOptimization: FunSpec({
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
ubyte source=99
|
||||
ubyte thingy=42
|
||||
ubyte @shared source=99
|
||||
ubyte @shared thingy=42
|
||||
|
||||
if source==3 or source==4 or source!=99 or source==1
|
||||
thingy++
|
||||
@ -691,8 +691,8 @@ class TestOptimization: FunSpec({
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
ubyte source=99
|
||||
ubyte thingy=42
|
||||
ubyte @shared source=99
|
||||
ubyte @shared thingy=42
|
||||
|
||||
if source==3 or source==4 or thingy==99 or source==1
|
||||
thingy++
|
||||
@ -709,8 +709,8 @@ class TestOptimization: FunSpec({
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
ubyte source=99
|
||||
ubyte thingy=42
|
||||
ubyte @shared source=99
|
||||
ubyte @shared thingy=42
|
||||
|
||||
if source==3 or source==4 and source==99 or source==1
|
||||
thingy++
|
||||
@ -727,7 +727,7 @@ class TestOptimization: FunSpec({
|
||||
val src="""
|
||||
main{
|
||||
sub start () {
|
||||
uword eRef
|
||||
uword @shared eRef
|
||||
if eRef[3] and 10 {
|
||||
return
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ class TestTypecasts: FunSpec({
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
bool bb2=true
|
||||
bool @shared bb2=true
|
||||
bool @shared bb = bb2 and true
|
||||
}
|
||||
}"""
|
||||
@ -73,10 +73,9 @@ main {
|
||||
}
|
||||
|
||||
sub start() {
|
||||
bool ub1 = true
|
||||
bool ub2 = true
|
||||
bool ub3 = true
|
||||
bool ub4 = 0
|
||||
bool @shared ub1 = true
|
||||
bool @shared ub2 = true
|
||||
bool @shared ub3 = true
|
||||
bool @shared bvalue
|
||||
|
||||
bvalue = ub1 xor ub2 xor ub3 xor true
|
||||
|
@ -153,7 +153,7 @@ main {
|
||||
val text="""
|
||||
main {
|
||||
sub start() {
|
||||
ubyte c = 1
|
||||
ubyte @shared c = 1
|
||||
@(15000 + c<<${'$'}0003) = 42
|
||||
@(15000 + (c<<${'$'}0003)) = 42
|
||||
@(15000 + c*${'$'}0008) = 42 ; *8 becomes a shift after opt
|
||||
@ -247,7 +247,7 @@ main {
|
||||
sub start() {
|
||||
|
||||
mylabel:
|
||||
ubyte variable
|
||||
ubyte @shared variable
|
||||
uword @shared pointer1 = &main.start
|
||||
uword @shared pointer2 = &start
|
||||
uword @shared pointer3 = &main.start.mylabel
|
||||
|
@ -152,9 +152,9 @@ mylabel_inside:
|
||||
val src = """
|
||||
main {
|
||||
sub start() {
|
||||
ubyte bytevar = 11 ; var at 0
|
||||
ubyte byteVAR = 22 ; var at 1
|
||||
ubyte ByteVar = 33 ; var at 2
|
||||
ubyte @shared bytevar = 11 ; var at 0
|
||||
ubyte @shared byteVAR = 22 ; var at 1
|
||||
ubyte @shared ByteVar = 33 ; var at 2
|
||||
ubyte @shared total = bytevar+byteVAR+ByteVar ; var at 3
|
||||
goto skipLABEL
|
||||
SkipLabel:
|
||||
|
@ -153,7 +153,7 @@ class BinaryExpression(
|
||||
var operator: String,
|
||||
var right: Expression,
|
||||
override val position: Position,
|
||||
val insideParentheses: Boolean = false // used in very few places to check priorities
|
||||
private val insideParentheses: Boolean = false
|
||||
) : Expression() {
|
||||
override lateinit var parent: Node
|
||||
|
||||
@ -178,6 +178,18 @@ class BinaryExpression(
|
||||
|
||||
override val isSimple = false
|
||||
|
||||
fun isChainedComparison(): Boolean {
|
||||
if(operator in ComparisonOperators) {
|
||||
val leftBinExpr = left as? BinaryExpression
|
||||
if (leftBinExpr != null && !leftBinExpr.insideParentheses && leftBinExpr.operator in ComparisonOperators)
|
||||
return true
|
||||
val rightBinExpr = right as? BinaryExpression
|
||||
if (rightBinExpr != null && !rightBinExpr.insideParentheses && rightBinExpr.operator in ComparisonOperators)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// binary expression should actually have been optimized away into a single value, before const value was requested...
|
||||
override fun constValue(program: Program): NumericLiteral? = null
|
||||
|
||||
@ -980,7 +992,7 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
|
||||
override val isSimple = true
|
||||
|
||||
fun targetStatement(program: Program) =
|
||||
if(nameInSource.size==1 && nameInSource[0] in program.builtinFunctions.names)
|
||||
if(nameInSource.singleOrNull() in program.builtinFunctions.names)
|
||||
BuiltinFunctionPlaceholder(nameInSource[0], position, parent)
|
||||
else
|
||||
definingScope.lookup(nameInSource)
|
||||
|
@ -141,30 +141,39 @@ class CallGraph(private val program: Program) : IAstVisitor {
|
||||
fun unused(module: Module) = module !in usedModules
|
||||
|
||||
fun unused(sub: Subroutine): Boolean {
|
||||
return sub !in usedSubroutines && !nameInAssemblyCode(sub.name)
|
||||
return sub !in usedSubroutines && !nameInAssemblyCode(sub.name, listOf("p8s_", ""))
|
||||
}
|
||||
|
||||
fun unused(block: Block): Boolean {
|
||||
return block !in usedBlocks && !nameInAssemblyCode(block.name)
|
||||
return block !in usedBlocks && !nameInAssemblyCode(block.name, listOf("p8b_", ""))
|
||||
}
|
||||
|
||||
fun unused(decl: VarDecl): Boolean {
|
||||
// Don't check assembly just for occurrences of variables, if they're not used in prog8 itself, just kill them
|
||||
// Don't check assembly just for occurrences of variables, if they're not used in prog8 itself, just kill them.
|
||||
// User should use @shared if they want to keep them.
|
||||
return usages(decl).isEmpty()
|
||||
}
|
||||
|
||||
fun usages(decl: VarDecl): List<IdentifierReference> {
|
||||
fun usages(decl: VarDecl): List<Node> {
|
||||
if(decl.type!=VarDeclType.VAR)
|
||||
return emptyList()
|
||||
|
||||
if(decl.definingBlock !in usedBlocks)
|
||||
return emptyList()
|
||||
|
||||
return allIdentifiersAndTargets.filter { decl===it.value }.map{ it.key }
|
||||
val assemblyBlocks = allAssemblyNodes.filter {
|
||||
decl.name in it.names || "p8v_" + decl.name in it.names
|
||||
}
|
||||
return allIdentifiersAndTargets.filter { decl===it.value }.map{ it.key } + assemblyBlocks
|
||||
}
|
||||
|
||||
private val prefixes = listOf("p8b_", "p8v_", "p8s_", "p8l_", "p8_", "")
|
||||
private fun nameInAssemblyCode(name: String): Boolean {
|
||||
private fun nameInAssemblyCode(name: String, knownAsmPrefixes: List<String> = emptyList()): Boolean {
|
||||
if(knownAsmPrefixes.isNotEmpty())
|
||||
return allAssemblyNodes.any {
|
||||
knownAsmPrefixes.any { prefix -> prefix+name in it.names }
|
||||
}
|
||||
|
||||
return allAssemblyNodes.any {
|
||||
prefixes.any { prefix -> prefix+name in it.names }
|
||||
}
|
||||
|
@ -2,6 +2,10 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- make constants have p8c_ prefix instead of p8v_
|
||||
- add INFO error level and move some warnings to info
|
||||
- add switch to enable INFO error messages (default is WARN and up)
|
||||
|
||||
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
||||
|
||||
...
|
||||
@ -56,8 +60,6 @@ Libraries:
|
||||
|
||||
Optimizations:
|
||||
|
||||
- give a warning for variables that could be a const - or even make them a const (if not @shared)?
|
||||
- treat every scalar variable decl with initialization value, as const by default, unless the variable gets assigned to somewhere (or has its address taken, or is @shared)
|
||||
- VariableAllocator: can we think of a smarter strategy for allocating variables into zeropage, rather than first-come-first-served?
|
||||
for instance, vars used inside loops first, then loopvars, then uwords used as pointers, then the rest
|
||||
- various optimizers skip stuff if compTarget.name==VMTarget.NAME. Once 6502-codegen is done from IR code,
|
||||
|
@ -17,6 +17,7 @@ mcf {
|
||||
ubyte file_channel
|
||||
|
||||
sub open(str filename, ubyte drive, ubyte channel) -> bool {
|
||||
file_channel = channel
|
||||
cbm.SETNAM(string.length(filename), filename)
|
||||
cbm.SETLFS(channel, drive, 2)
|
||||
void cbm.OPEN()
|
||||
|
@ -24,8 +24,8 @@ main {
|
||||
for i in 0 to len(s2)-1
|
||||
txt.setchr(i, 1, s2[i])
|
||||
|
||||
ubyte c1 = 'z'
|
||||
ubyte c2 = sc:'z'
|
||||
const ubyte c1 = 'z'
|
||||
const ubyte c2 = sc:'z'
|
||||
|
||||
txt.print("\npetscii z=")
|
||||
txt.print_ub(c1)
|
||||
|
@ -13,5 +13,7 @@ main {
|
||||
txt.nl()
|
||||
txt.print_ub(5<(x-y)<=9<y)
|
||||
txt.nl()
|
||||
txt.print_ub(5<(x-y)<=9<(y+40))
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user