mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
removal of unused nodes
This commit is contained in:
parent
cc73d90d6e
commit
3e11d45883
@ -11,12 +11,15 @@
|
|||||||
~ extra233 {
|
~ extra233 {
|
||||||
; this is imported
|
; this is imported
|
||||||
|
|
||||||
X = 42
|
const byte snerp=33
|
||||||
return 44
|
const byte snerp2 = snerp+22
|
||||||
|
|
||||||
sub foo() -> () {
|
X = 42+snerp
|
||||||
A=99
|
return 44+snerp
|
||||||
return
|
|
||||||
|
sub foo234234() -> () {
|
||||||
|
A=99+snerp
|
||||||
|
return A+snerp2
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,20 +14,27 @@ fun main(args: Array<String>) {
|
|||||||
println("\nIL65 compiler by Irmen de Jong (irmen@razorvine.net)")
|
println("\nIL65 compiler by Irmen de Jong (irmen@razorvine.net)")
|
||||||
println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
|
println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
|
||||||
|
|
||||||
|
// import main module and process additional imports
|
||||||
|
|
||||||
val filepath = Paths.get(args[0]).normalize()
|
val filepath = Paths.get(args[0]).normalize()
|
||||||
val moduleAst = importModule(filepath)
|
val moduleAst = importModule(filepath)
|
||||||
moduleAst.linkParents()
|
moduleAst.linkParents()
|
||||||
val globalNamespace = moduleAst.namespace()
|
val globalNamespace = moduleAst.namespace()
|
||||||
//globalNamespace.debugPrint()
|
//globalNamespace.debugPrint()
|
||||||
|
|
||||||
|
|
||||||
|
// perform syntax checks and optimizations
|
||||||
|
|
||||||
moduleAst.checkIdentifiers(globalNamespace)
|
moduleAst.checkIdentifiers(globalNamespace)
|
||||||
moduleAst.optimizeExpressions(globalNamespace)
|
moduleAst.optimizeExpressions(globalNamespace)
|
||||||
moduleAst.optimizeStatements(globalNamespace)
|
val allScopedSymbolDefinitions = moduleAst.checkIdentifiers(globalNamespace)
|
||||||
|
moduleAst.optimizeStatements(globalNamespace, allScopedSymbolDefinitions)
|
||||||
val globalNamespaceAfterOptimize = moduleAst.namespace() // it could have changed in the meantime
|
val globalNamespaceAfterOptimize = moduleAst.namespace() // it could have changed in the meantime
|
||||||
moduleAst.checkValid(globalNamespaceAfterOptimize) // check if final tree is valid
|
moduleAst.checkValid(globalNamespaceAfterOptimize) // check if final tree is valid
|
||||||
val allScopedSymbolDefinitions = moduleAst.checkIdentifiers(globalNamespace)
|
|
||||||
|
|
||||||
// determine special compiler options
|
// determine special compiler options
|
||||||
|
|
||||||
val options = moduleAst.statements.filter { it is Directive && it.directive=="%option" }.flatMap { (it as Directive).args }.toSet()
|
val options = moduleAst.statements.filter { it is Directive && it.directive=="%option" }.flatMap { (it as Directive).args }.toSet()
|
||||||
val outputType = (moduleAst.statements.singleOrNull { it is Directive && it.directive=="%output"}
|
val outputType = (moduleAst.statements.singleOrNull { it is Directive && it.directive=="%output"}
|
||||||
as? Directive)?.args?.single()?.name?.toUpperCase()
|
as? Directive)?.args?.single()?.name?.toUpperCase()
|
||||||
@ -42,6 +49,10 @@ fun main(args: Array<String>) {
|
|||||||
if(zpType==null) ZeropageType.COMPATIBLE else ZeropageType.valueOf(zpType),
|
if(zpType==null) ZeropageType.COMPATIBLE else ZeropageType.valueOf(zpType),
|
||||||
options.contains(DirectiveArg(null, "enable_floats", null))
|
options.contains(DirectiveArg(null, "enable_floats", null))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// compile the syntax tree into intermediate form, and optimize that
|
||||||
|
|
||||||
val compiler = Compiler(compilerOptions, globalNamespaceAfterOptimize)
|
val compiler = Compiler(compilerOptions, globalNamespaceAfterOptimize)
|
||||||
val intermediate = compiler.compile(moduleAst)
|
val intermediate = compiler.compile(moduleAst)
|
||||||
intermediate.optimize()
|
intermediate.optimize()
|
||||||
@ -49,8 +60,8 @@ fun main(args: Array<String>) {
|
|||||||
// val assembler = intermediate.compileToAssembly()
|
// val assembler = intermediate.compileToAssembly()
|
||||||
// assembler.assemble(compilerOptions, "input", "output")
|
// assembler.assemble(compilerOptions, "input", "output")
|
||||||
// val monitorfile = assembler.generateBreakpointList()
|
// val monitorfile = assembler.generateBreakpointList()
|
||||||
|
//
|
||||||
// start the vice emulator
|
// // start the vice emulator
|
||||||
// val program = "foo"
|
// val program = "foo"
|
||||||
// val cmdline = listOf("x64", "-moncommands", monitorfile,
|
// val cmdline = listOf("x64", "-moncommands", monitorfile,
|
||||||
// "-autostartprgmode", "1", "-autostart-warp", "-autostart", program)
|
// "-autostartprgmode", "1", "-autostart-warp", "-autostart", program)
|
||||||
@ -61,5 +72,3 @@ fun main(args: Array<String>) {
|
|||||||
exitProcess(1)
|
exitProcess(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,50 +61,62 @@ class ExpressionException(message: String, val position: Position?) : AstExcepti
|
|||||||
|
|
||||||
|
|
||||||
data class Position(val file: String, val line: Int, val startCol: Int, val endCol: Int) {
|
data class Position(val file: String, val line: Int, val startCol: Int, val endCol: Int) {
|
||||||
override fun toString(): String = "[$file: line $line col $startCol-$endCol]"
|
override fun toString(): String = "[$file: line $line col ${startCol+1}-${endCol+1}]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface IAstProcessor {
|
interface IAstProcessor {
|
||||||
fun process(module: Module) {
|
fun process(module: Module) {
|
||||||
module.statements = module.statements.map { it.process(this) }
|
module.statements = module.statements.map { it.process(this) }.toMutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun process(expr: PrefixExpression): IExpression {
|
fun process(expr: PrefixExpression): IExpression {
|
||||||
expr.expression = expr.expression.process(this)
|
expr.expression = expr.expression.process(this)
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
fun process(expr: BinaryExpression): IExpression {
|
fun process(expr: BinaryExpression): IExpression {
|
||||||
expr.left = expr.left.process(this)
|
expr.left = expr.left.process(this)
|
||||||
expr.right = expr.right.process(this)
|
expr.right = expr.right.process(this)
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
fun process(directive: Directive): IStatement {
|
fun process(directive: Directive): IStatement {
|
||||||
return directive
|
return directive
|
||||||
}
|
}
|
||||||
|
|
||||||
fun process(block: Block): IStatement {
|
fun process(block: Block): IStatement {
|
||||||
block.statements = block.statements.map { it.process(this) }
|
block.statements = block.statements.map { it.process(this) }.toMutableList()
|
||||||
return block
|
return block
|
||||||
}
|
}
|
||||||
|
|
||||||
fun process(decl: VarDecl): IStatement {
|
fun process(decl: VarDecl): IStatement {
|
||||||
decl.value = decl.value?.process(this)
|
decl.value = decl.value?.process(this)
|
||||||
decl.arrayspec?.process(this)
|
decl.arrayspec?.process(this)
|
||||||
return decl
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
fun process(subroutine: Subroutine): IStatement {
|
fun process(subroutine: Subroutine): IStatement {
|
||||||
subroutine.statements = subroutine.statements.map { it.process(this) }
|
subroutine.statements = subroutine.statements.map { it.process(this) }.toMutableList()
|
||||||
return subroutine
|
return subroutine
|
||||||
}
|
}
|
||||||
|
|
||||||
fun process(functionCall: FunctionCall): IExpression {
|
fun process(functionCall: FunctionCall): IExpression {
|
||||||
functionCall.arglist = functionCall.arglist.map { it.process(this) }
|
functionCall.arglist = functionCall.arglist.map { it.process(this) }
|
||||||
return functionCall
|
return functionCall
|
||||||
}
|
}
|
||||||
|
|
||||||
fun process(functionCall: FunctionCallStatement): IStatement {
|
fun process(functionCall: FunctionCallStatement): IStatement {
|
||||||
functionCall.arglist = functionCall.arglist.map { it.process(this) }
|
functionCall.arglist = functionCall.arglist.map { it.process(this) }
|
||||||
return functionCall
|
return functionCall
|
||||||
}
|
}
|
||||||
|
|
||||||
fun process(identifier: IdentifierReference): IExpression {
|
fun process(identifier: IdentifierReference): IExpression {
|
||||||
|
// note: this is an identifier that is used in an expression.
|
||||||
|
// other identifiers are simply part of the other statements (such as jumps, subroutine defs etc)
|
||||||
return identifier
|
return identifier
|
||||||
}
|
}
|
||||||
|
|
||||||
fun process(jump: Jump): IStatement {
|
fun process(jump: Jump): IStatement {
|
||||||
return jump
|
return jump
|
||||||
}
|
}
|
||||||
@ -137,7 +149,7 @@ interface Node {
|
|||||||
|
|
||||||
interface IStatement : Node {
|
interface IStatement : Node {
|
||||||
fun process(processor: IAstProcessor) : IStatement
|
fun process(processor: IAstProcessor) : IStatement
|
||||||
fun scopedName(name: String): String {
|
fun makeScopedName(name: String): List<String> {
|
||||||
val scope = mutableListOf<String>()
|
val scope = mutableListOf<String>()
|
||||||
var statementScope = this.parent
|
var statementScope = this.parent
|
||||||
while(statementScope!=null && statementScope !is Module) {
|
while(statementScope!=null && statementScope !is Module) {
|
||||||
@ -147,7 +159,7 @@ interface IStatement : Node {
|
|||||||
statementScope = statementScope.parent
|
statementScope = statementScope.parent
|
||||||
}
|
}
|
||||||
scope.add(name)
|
scope.add(name)
|
||||||
return scope.joinToString(".")
|
return scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +172,11 @@ interface IFunctionCall {
|
|||||||
interface INameScope {
|
interface INameScope {
|
||||||
val name: String
|
val name: String
|
||||||
val position: Position?
|
val position: Position?
|
||||||
var statements: List<IStatement>
|
var statements: MutableList<IStatement>
|
||||||
|
|
||||||
|
fun usedNames(): Set<String>
|
||||||
|
|
||||||
|
fun registerUsedName(name: String)
|
||||||
|
|
||||||
fun subScopes() = statements.filter { it is INameScope } .map { it as INameScope }.associate { it.name to it }
|
fun subScopes() = statements.filter { it is INameScope } .map { it as INameScope }.associate { it.name to it }
|
||||||
|
|
||||||
@ -188,6 +204,9 @@ interface INameScope {
|
|||||||
statementScope = statementScope.parent
|
statementScope = statementScope.parent
|
||||||
if (statementScope == null)
|
if (statementScope == null)
|
||||||
return null
|
return null
|
||||||
|
if(statementScope.parent==null && statementScope !is Module)
|
||||||
|
throw AstException("non-Module node has no parent! node: $statementScope at ${statementScope.position}")
|
||||||
|
|
||||||
val localScope = statementScope as INameScope
|
val localScope = statementScope as INameScope
|
||||||
val result = localScope.definedNames()[scopedName[0]]
|
val result = localScope.definedNames()[scopedName[0]]
|
||||||
if (result != null)
|
if (result != null)
|
||||||
@ -213,6 +232,12 @@ interface INameScope {
|
|||||||
}
|
}
|
||||||
printNames(0, this)
|
printNames(0, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removeStatement(statement: IStatement) {
|
||||||
|
// remove a statement (most likely because it is never referenced such as a subroutine)
|
||||||
|
val removed = statements.remove(statement)
|
||||||
|
if(!removed) throw AstException("node to remove wasn't found")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -236,13 +261,14 @@ data class AnonymousStatementList(override var parent: Node?, var statements: Li
|
|||||||
|
|
||||||
|
|
||||||
data class Module(override val name: String,
|
data class Module(override val name: String,
|
||||||
override var statements: List<IStatement>) : Node, INameScope {
|
override var statements: MutableList<IStatement>) : Node, INameScope {
|
||||||
override var position: Position? = null
|
override var position: Position? = null
|
||||||
override var parent: Node? = null
|
override var parent: Node? = null
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
this.parent=parent
|
this.parent=parent
|
||||||
}
|
}
|
||||||
|
|
||||||
fun linkParents() {
|
fun linkParents() {
|
||||||
parent = null
|
parent = null
|
||||||
statements.forEach {it.linkParents(this)}
|
statements.forEach {it.linkParents(this)}
|
||||||
@ -254,17 +280,44 @@ data class Module(override val name: String,
|
|||||||
|
|
||||||
fun namespace(): INameScope {
|
fun namespace(): INameScope {
|
||||||
class GlobalNamespace(override val name: String,
|
class GlobalNamespace(override val name: String,
|
||||||
override var statements: List<IStatement>,
|
override var statements: MutableList<IStatement>,
|
||||||
override val position: Position?) : INameScope
|
override val position: Position?) : INameScope {
|
||||||
|
|
||||||
|
private val scopedNamesUsed: MutableSet<String> = mutableSetOf("main") // main is always used
|
||||||
|
|
||||||
|
override fun usedNames(): Set<String> = scopedNamesUsed
|
||||||
|
|
||||||
|
override fun lookup(scopedName: List<String>, statement: Node): IStatement? {
|
||||||
|
val stmt = super.lookup(scopedName, statement)
|
||||||
|
if(stmt!=null) {
|
||||||
|
val targetScopedName = when(stmt) {
|
||||||
|
is Label -> stmt.makeScopedName(stmt.name)
|
||||||
|
is VarDecl -> stmt.makeScopedName(stmt.name)
|
||||||
|
is Block -> stmt.makeScopedName(stmt.name)
|
||||||
|
is Subroutine -> stmt.makeScopedName(stmt.name)
|
||||||
|
else -> throw NameError("wrong identifier target: $stmt", stmt.position)
|
||||||
|
}
|
||||||
|
registerUsedName(targetScopedName.joinToString("."))
|
||||||
|
}
|
||||||
|
return stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerUsedName(name: String) {
|
||||||
|
scopedNamesUsed.add(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return GlobalNamespace("<<<global>>>", statements, position)
|
return GlobalNamespace("<<<global>>>", statements, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun usedNames(): Set<String> = throw NotImplementedError("not implemented on sub-scopes")
|
||||||
|
override fun registerUsedName(name: String) = throw NotImplementedError("not implemented on sub-scopes")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class Block(override val name: String,
|
data class Block(override val name: String,
|
||||||
val address: Int?,
|
val address: Int?,
|
||||||
override var statements: List<IStatement>) : IStatement, INameScope {
|
override var statements: MutableList<IStatement>) : IStatement, INameScope {
|
||||||
override var position: Position? = null
|
override var position: Position? = null
|
||||||
override var parent: Node? = null
|
override var parent: Node? = null
|
||||||
|
|
||||||
@ -278,6 +331,9 @@ data class Block(override val name: String,
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Block(name=$name, address=$address, ${statements.size} statements)"
|
return "Block(name=$name, address=$address, ${statements.size} statements)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun usedNames(): Set<String> = throw NotImplementedError("not implemented on sub-scopes")
|
||||||
|
override fun registerUsedName(name: String) = throw NotImplementedError("not implemented on sub-scopes")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -533,7 +589,7 @@ data class RegisterExpr(val register: Register) : IExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class IdentifierReference(val scopedName: List<String>) : IExpression {
|
data class IdentifierReference(val nameInSource: List<String>) : IExpression {
|
||||||
override var position: Position? = null
|
override var position: Position? = null
|
||||||
override var parent: Node? = null
|
override var parent: Node? = null
|
||||||
|
|
||||||
@ -542,9 +598,9 @@ data class IdentifierReference(val scopedName: List<String>) : IExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun constValue(namespace: INameScope): LiteralValue? {
|
override fun constValue(namespace: INameScope): LiteralValue? {
|
||||||
val node = namespace.lookup(scopedName, this)
|
val node = namespace.lookup(nameInSource, this)
|
||||||
?:
|
?:
|
||||||
throw ExpressionException("undefined symbol: ${scopedName.joinToString(".")}", position)
|
throw ExpressionException("undefined symbol: ${nameInSource.joinToString(".")}", position)
|
||||||
val vardecl = node as? VarDecl
|
val vardecl = node as? VarDecl
|
||||||
if(vardecl==null) {
|
if(vardecl==null) {
|
||||||
throw ExpressionException("name should be a constant, instead of: ${node::class.simpleName}", position)
|
throw ExpressionException("name should be a constant, instead of: ${node::class.simpleName}", position)
|
||||||
@ -555,7 +611,7 @@ data class IdentifierReference(val scopedName: List<String>) : IExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun process(processor: IAstProcessor) = processor.process(this)
|
override fun process(processor: IAstProcessor) = processor.process(this)
|
||||||
override fun referencesIdentifier(name: String): Boolean = scopedName.last() == name // @todo is this correct all the time?
|
override fun referencesIdentifier(name: String): Boolean = nameInSource.last() == name // @todo is this correct all the time?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -600,8 +656,8 @@ data class FunctionCall(override var target: IdentifierReference, override var a
|
|||||||
|
|
||||||
override fun constValue(namespace: INameScope): LiteralValue? {
|
override fun constValue(namespace: INameScope): LiteralValue? {
|
||||||
// if the function is a built-in function and the args are consts, should evaluate!
|
// if the function is a built-in function and the args are consts, should evaluate!
|
||||||
if(target.scopedName.size>1) return null
|
if(target.nameInSource.size>1) return null
|
||||||
return when(target.scopedName[0]){
|
return when(target.nameInSource[0]){
|
||||||
"sin" -> builtin_sin(arglist, position, namespace)
|
"sin" -> builtin_sin(arglist, position, namespace)
|
||||||
"cos" -> builtin_cos(arglist, position, namespace)
|
"cos" -> builtin_cos(arglist, position, namespace)
|
||||||
"abs" -> builtin_abs(arglist, position, namespace)
|
"abs" -> builtin_abs(arglist, position, namespace)
|
||||||
@ -656,15 +712,15 @@ data class Subroutine(override val name: String,
|
|||||||
val parameters: List<SubroutineParameter>,
|
val parameters: List<SubroutineParameter>,
|
||||||
val returnvalues: List<SubroutineReturnvalue>,
|
val returnvalues: List<SubroutineReturnvalue>,
|
||||||
val address: Int?,
|
val address: Int?,
|
||||||
override var statements: List<IStatement>) : IStatement, INameScope {
|
override var statements: MutableList<IStatement>) : IStatement, INameScope {
|
||||||
override var position: Position? = null
|
override var position: Position? = null
|
||||||
override var parent: Node? = null
|
override var parent: Node? = null
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
this.parent = parent
|
this.parent = parent
|
||||||
parameters.forEach { it.parent=this }
|
parameters.forEach { it.linkParents(this) }
|
||||||
returnvalues.forEach { it.parent=this }
|
returnvalues.forEach { it.linkParents(this) }
|
||||||
statements.forEach { it.parent=this }
|
statements.forEach { it.linkParents(this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun process(processor: IAstProcessor) = processor.process(this)
|
override fun process(processor: IAstProcessor) = processor.process(this)
|
||||||
@ -672,6 +728,9 @@ data class Subroutine(override val name: String,
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Subroutine(name=$name, address=$address, parameters=$parameters, returnvalues=$returnvalues, ${statements.size} statements)"
|
return "Subroutine(name=$name, address=$address, parameters=$parameters, returnvalues=$returnvalues, ${statements.size} statements)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun usedNames(): Set<String> = throw NotImplementedError("not implemented on sub-scopes")
|
||||||
|
override fun registerUsedName(name: String) = throw NotImplementedError("not implemented on sub-scopes")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -715,7 +774,7 @@ data class IfStatement(var condition: IExpression,
|
|||||||
/***************** Antlr Extension methods to create AST ****************/
|
/***************** Antlr Extension methods to create AST ****************/
|
||||||
|
|
||||||
fun il65Parser.ModuleContext.toAst(name: String, withPosition: Boolean) : Module {
|
fun il65Parser.ModuleContext.toAst(name: String, withPosition: Boolean) : Module {
|
||||||
val module = Module(name, modulestatement().map { it.toAst(withPosition) })
|
val module = Module(name, modulestatement().map { it.toAst(withPosition) }.toMutableList())
|
||||||
module.position = toPosition(withPosition)
|
module.position = toPosition(withPosition)
|
||||||
return module
|
return module
|
||||||
}
|
}
|
||||||
@ -753,8 +812,8 @@ private fun il65Parser.BlockContext.toAst(withPosition: Boolean) : IStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun il65Parser.Statement_blockContext.toAst(withPosition: Boolean): List<IStatement>
|
private fun il65Parser.Statement_blockContext.toAst(withPosition: Boolean): MutableList<IStatement>
|
||||||
= statement().map { it.toAst(withPosition) }
|
= statement().map { it.toAst(withPosition) }.toMutableList()
|
||||||
|
|
||||||
|
|
||||||
private fun il65Parser.StatementContext.toAst(withPosition: Boolean) : IStatement {
|
private fun il65Parser.StatementContext.toAst(withPosition: Boolean) : IStatement {
|
||||||
@ -918,7 +977,7 @@ private fun il65Parser.SubroutineContext.toAst(withPosition: Boolean) : Subrouti
|
|||||||
if(sub_params()==null) emptyList() else sub_params().toAst(),
|
if(sub_params()==null) emptyList() else sub_params().toAst(),
|
||||||
if(sub_returns()==null) emptyList() else sub_returns().toAst(),
|
if(sub_returns()==null) emptyList() else sub_returns().toAst(),
|
||||||
sub_address()?.integerliteral()?.toAst(),
|
sub_address()?.integerliteral()?.toAst(),
|
||||||
if(statement_block()==null) emptyList() else statement_block().toAst(withPosition))
|
if(statement_block()==null) mutableListOf() else statement_block().toAst(withPosition))
|
||||||
sub.position = toPosition(withPosition)
|
sub.position = toPosition(withPosition)
|
||||||
return sub
|
return sub
|
||||||
}
|
}
|
||||||
|
@ -309,8 +309,8 @@ class AstChecker(private val globalNamespace: INameScope) : IAstProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkFunctionExists(target: IdentifierReference, statement: IStatement) {
|
private fun checkFunctionExists(target: IdentifierReference, statement: IStatement) {
|
||||||
if(globalNamespace.lookup(target.scopedName, statement)==null)
|
if(globalNamespace.lookup(target.nameInSource, statement)==null)
|
||||||
checkResult.add(SyntaxError("undefined function or subroutine: ${target.scopedName.joinToString(".")}", statement.position))
|
checkResult.add(SyntaxError("undefined function or subroutine: ${target.nameInSource.joinToString(".")}", statement.position))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkValueRange(datatype: DataType, value: LiteralValue, position: Position?) : Boolean {
|
private fun checkValueRange(datatype: DataType, value: LiteralValue, position: Position?) : Boolean {
|
||||||
|
@ -35,50 +35,46 @@ class AstIdentifiersChecker(private val globalNamespace: INameScope) : IAstProce
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun process(block: Block): IStatement {
|
override fun process(block: Block): IStatement {
|
||||||
val scopedName = block.scopedName(block.name)
|
val scopedName = block.makeScopedName(block.name).joinToString(".")
|
||||||
val existing = symbols[scopedName]
|
val existing = symbols[scopedName]
|
||||||
if(existing!=null) {
|
if(existing!=null) {
|
||||||
nameError(block.name, block.position, existing)
|
nameError(block.name, block.position, existing)
|
||||||
} else {
|
} else {
|
||||||
symbols[scopedName] = block
|
symbols[scopedName] = block
|
||||||
}
|
}
|
||||||
super.process(block)
|
return super.process(block)
|
||||||
return block
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun process(decl: VarDecl): IStatement {
|
override fun process(decl: VarDecl): IStatement {
|
||||||
val scopedName = decl.scopedName(decl.name)
|
val scopedName = decl.makeScopedName(decl.name).joinToString(".")
|
||||||
val existing = symbols[scopedName]
|
val existing = symbols[scopedName]
|
||||||
if(existing!=null) {
|
if(existing!=null) {
|
||||||
nameError(decl.name, decl.position, existing)
|
nameError(decl.name, decl.position, existing)
|
||||||
} else {
|
} else {
|
||||||
symbols[scopedName] = decl
|
symbols[scopedName] = decl
|
||||||
}
|
}
|
||||||
super.process(decl)
|
return super.process(decl)
|
||||||
return decl
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun process(subroutine: Subroutine): IStatement {
|
override fun process(subroutine: Subroutine): IStatement {
|
||||||
val scopedName = subroutine.scopedName(subroutine.name)
|
val scopedName = subroutine.makeScopedName(subroutine.name).joinToString(".")
|
||||||
val existing = symbols[scopedName]
|
val existing = symbols[scopedName]
|
||||||
if(existing!=null) {
|
if(existing!=null) {
|
||||||
nameError(subroutine.name, subroutine.position, existing)
|
nameError(subroutine.name, subroutine.position, existing)
|
||||||
} else {
|
} else {
|
||||||
symbols[scopedName] = subroutine
|
symbols[scopedName] = subroutine
|
||||||
}
|
}
|
||||||
super.process(subroutine)
|
return super.process(subroutine)
|
||||||
return subroutine
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun process(label: Label): IStatement {
|
override fun process(label: Label): IStatement {
|
||||||
val scopedName = label.scopedName(label.name)
|
val scopedName = label.makeScopedName(label.name).joinToString(".")
|
||||||
val existing = symbols[scopedName]
|
val existing = symbols[scopedName]
|
||||||
if(existing!=null) {
|
if(existing!=null) {
|
||||||
nameError(label.name, label.position, existing)
|
nameError(label.name, label.position, existing)
|
||||||
} else {
|
} else {
|
||||||
symbols[scopedName] = label
|
symbols[scopedName] = label
|
||||||
}
|
}
|
||||||
super.process(label)
|
return super.process(label)
|
||||||
return label
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,8 @@ class AssemblyResult(val name: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun genereateBreakpointList(): String {
|
fun generateBreakpointList(): String {
|
||||||
|
// todo build breakpoint list!
|
||||||
/*
|
/*
|
||||||
def generate_breakpoint_list(self, program_filename: str) -> str:
|
def generate_breakpoint_list(self, program_filename: str) -> str:
|
||||||
breakpoints = []
|
breakpoints = []
|
||||||
|
@ -3,9 +3,10 @@ package il65.optimizing
|
|||||||
import il65.ast.*
|
import il65.ast.*
|
||||||
|
|
||||||
|
|
||||||
fun Module.optimizeStatements(globalNamespace: INameScope) {
|
fun Module.optimizeStatements(globalNamespace: INameScope, allScopedSymbolDefinitions: MutableMap<String, IStatement>) {
|
||||||
val optimizer = StatementOptimizer(globalNamespace)
|
val optimizer = StatementOptimizer(globalNamespace)
|
||||||
this.process(optimizer)
|
this.process(optimizer)
|
||||||
|
optimizer.removeUnusedNodes(globalNamespace.usedNames(), allScopedSymbolDefinitions)
|
||||||
if(optimizer.optimizationsDone==0)
|
if(optimizer.optimizationsDone==0)
|
||||||
println("[${this.name}] 0 optimizations performed")
|
println("[${this.name}] 0 optimizations performed")
|
||||||
|
|
||||||
@ -18,7 +19,6 @@ fun Module.optimizeStatements(globalNamespace: INameScope) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
todo remove unused blocks, subroutines and variable decls (replace with empty AnonymousStatementList)
|
|
||||||
todo statement optimization: create augmented assignment from assignment that only refers to its lvalue (A=A+10, A=4*A, ...)
|
todo statement optimization: create augmented assignment from assignment that only refers to its lvalue (A=A+10, A=4*A, ...)
|
||||||
todo statement optimization: X+=1, X-=1 --> X++/X-- ,
|
todo statement optimization: X+=1, X-=1 --> X++/X-- ,
|
||||||
todo remove statements that have no effect X=X , X+=0, X-=0, X*=1, X/=1, X//=1, A |= 0, A ^= 0, A<<=0, etc etc
|
todo remove statements that have no effect X=X , X+=0, X-=0, X*=1, X/=1, X//=1, A |= 0, A ^= 0, A<<=0, etc etc
|
||||||
@ -37,6 +37,32 @@ class StatementOptimizer(private val globalNamespace: INameScope) : IAstProcesso
|
|||||||
optimizationsDone = 0
|
optimizationsDone = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun process(functionCall: FunctionCall): IExpression {
|
||||||
|
val function = globalNamespace.lookup(functionCall.target.nameInSource, functionCall)
|
||||||
|
if(function!=null) {
|
||||||
|
val scopedName = when(function) {
|
||||||
|
is Label -> function.makeScopedName(function.name)
|
||||||
|
is Subroutine -> function.makeScopedName(function.name)
|
||||||
|
else -> throw AstException("invalid function call target node type")
|
||||||
|
}
|
||||||
|
globalNamespace.registerUsedName(scopedName.joinToString("."))
|
||||||
|
}
|
||||||
|
return super.process(functionCall)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun process(functionCall: FunctionCallStatement): IStatement {
|
||||||
|
val function = globalNamespace.lookup(functionCall.target.nameInSource, functionCall)
|
||||||
|
if(function!=null) {
|
||||||
|
val scopedName = when(function) {
|
||||||
|
is Label -> function.makeScopedName(function.name)
|
||||||
|
is Subroutine -> function.makeScopedName(function.name)
|
||||||
|
else -> throw AstException("invalid function call target node type")
|
||||||
|
}
|
||||||
|
globalNamespace.registerUsedName(scopedName.joinToString("."))
|
||||||
|
}
|
||||||
|
return super.process(functionCall)
|
||||||
|
}
|
||||||
|
|
||||||
override fun process(ifStatement: IfStatement): IStatement {
|
override fun process(ifStatement: IfStatement): IStatement {
|
||||||
super.process(ifStatement)
|
super.process(ifStatement)
|
||||||
val constvalue = ifStatement.condition.constValue(globalNamespace)
|
val constvalue = ifStatement.condition.constValue(globalNamespace)
|
||||||
@ -53,4 +79,16 @@ class StatementOptimizer(private val globalNamespace: INameScope) : IAstProcesso
|
|||||||
}
|
}
|
||||||
return ifStatement
|
return ifStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removeUnusedNodes(usedNames: Set<String>, allScopedSymbolDefinitions: MutableMap<String, IStatement>) {
|
||||||
|
for ((name, value) in allScopedSymbolDefinitions) {
|
||||||
|
if(!usedNames.contains(name)) {
|
||||||
|
val parentScope = value.parent as INameScope
|
||||||
|
val localname = name.substringAfterLast(".")
|
||||||
|
println("${value.position} Warning: ${value::class.simpleName} '$localname' is never used")
|
||||||
|
parentScope.removeStatement(value)
|
||||||
|
optimizationsDone++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user