fix symbol usage tracking, also track scopes themselves. Fix directive option comparisons.

This commit is contained in:
Irmen de Jong 2018-09-05 22:51:34 +02:00
parent cd6327850e
commit 28ab7bbe34
6 changed files with 48 additions and 30 deletions

View File

@ -106,7 +106,7 @@
P_irqd(1)
} else X=33
X= extra233.thingy() ; TODO EHHHH, should be counted as used?
X= extra233.thingy()
if(6>36) {
@ -131,7 +131,7 @@ cool:
mega:
cool:
sub ultrafoo() -> () {
X= extra233.thingy() ; TODO EHHHH, should be counted as used?
X= extra233.thingy()
return 33
goto main.mega
}

7
il65/il65.sh Executable file
View File

@ -0,0 +1,7 @@
#/bin/env sh
IL65_LIBDIR=../lib65
IL65CLASSPATH=out/production/il65
LIBJARS=/opt/irmen/idea-2018/plugins/Kotlin/lib/kotlin-stdlib.jar:antlr/lib/antlr-runtime-4.7.1.jar
java -Dil65.libdir=${IL65_LIBDIR} -cp ${IL65CLASSPATH}:${LIBJARS} il65.MainKt $*

View File

@ -27,19 +27,6 @@ fun main(args: Array<String>) {
moduleAst.linkParents()
val globalNameSpaceBeforeOptimization = moduleAst.definingScope()
// perform syntax checks and optimizations
moduleAst.checkIdentifiers()
moduleAst.optimizeExpressions(globalNameSpaceBeforeOptimization)
moduleAst.checkValid(globalNameSpaceBeforeOptimization) // check if tree is valid
val allScopedSymbolDefinitions = moduleAst.checkIdentifiers()
moduleAst.optimizeStatements(globalNameSpaceBeforeOptimization, allScopedSymbolDefinitions)
val globalNamespaceAfterOptimize = moduleAst.definingScope() // it could have changed in the meantime
moduleAst.checkValid(globalNamespaceAfterOptimize) // check if final tree is valid
moduleAst.checkRecursion() // check if there are recursive subroutine calls
// globalNamespaceAfterOptimize.debugPrint()
// determine special compiler options
val options = moduleAst.statements.filter { it is Directive && it.directive=="%option" }.flatMap { (it as Directive).args }.toSet()
@ -58,6 +45,19 @@ fun main(args: Array<String>) {
)
// perform syntax checks and optimizations
moduleAst.checkIdentifiers()
moduleAst.optimizeExpressions(globalNameSpaceBeforeOptimization)
moduleAst.checkValid(globalNameSpaceBeforeOptimization, compilerOptions) // check if tree is valid
val allScopedSymbolDefinitions = moduleAst.checkIdentifiers()
moduleAst.optimizeStatements(globalNameSpaceBeforeOptimization, allScopedSymbolDefinitions)
val globalNamespaceAfterOptimize = moduleAst.definingScope() // it could have changed in the meantime
moduleAst.checkValid(globalNamespaceAfterOptimize, compilerOptions) // check if final tree is valid
moduleAst.checkRecursion() // check if there are recursive subroutine calls
// globalNamespaceAfterOptimize.debugPrint()
// compile the syntax tree into intermediate form, and optimize that
val compiler = Compiler(compilerOptions, globalNamespaceAfterOptimize)

View File

@ -383,7 +383,10 @@ class Module(override val name: String,
}
override fun registerUsedName(name: String) {
// make sure to also register each scope separately
scopedNamesUsed.add(name)
if(name.contains('.'))
registerUsedName(name.substringBeforeLast('.'))
}
}
}
@ -412,7 +415,7 @@ class Block(override val name: String,
}
class Directive(val directive: String, val args: List<DirectiveArg>) : IStatement {
data class Directive(val directive: String, val args: List<DirectiveArg>) : IStatement {
override var position: Position? = null
override lateinit var parent: Node
@ -425,7 +428,7 @@ class Directive(val directive: String, val args: List<DirectiveArg>) : IStatemen
}
class DirectiveArg(val str: String?, val name: String?, val int: Int?) : Node {
data class DirectiveArg(val str: String?, val name: String?, val int: Int?) : Node {
override var position: Position? = null
override lateinit var parent: Node
@ -435,7 +438,7 @@ class DirectiveArg(val str: String?, val name: String?, val int: Int?) : Node {
}
class Label(val name: String) : IStatement {
data class Label(val name: String) : IStatement {
override var position: Position? = null
override lateinit var parent: Node
val scopedname: List<String> by lazy { makeScopedName(name) }
@ -542,7 +545,7 @@ class Assignment(var target: AssignTarget, val aug_op : String?, var value: IExp
}
}
class AssignTarget(val register: Register?, val identifier: IdentifierReference?) : Node {
data class AssignTarget(val register: Register?, val identifier: IdentifierReference?) : Node {
override var position: Position? = null
override lateinit var parent: Node
@ -597,7 +600,7 @@ class BinaryExpression(var left: IExpression, val operator: String, var right: I
override fun referencesIdentifier(name: String) = left.referencesIdentifier(name) || right.referencesIdentifier(name)
}
class LiteralValue(val intvalue: Int? = null,
data class LiteralValue(val intvalue: Int? = null,
val floatvalue: Double? = null,
val strvalue: String? = null,
val arrayvalue: MutableList<IExpression>? = null) : IExpression {
@ -667,7 +670,7 @@ class RegisterExpr(val register: Register) : IExpression {
}
class IdentifierReference(val nameInSource: List<String>) : IExpression {
data class IdentifierReference(val nameInSource: List<String>) : IExpression {
override var position: Position? = null
override lateinit var parent: Node
@ -849,7 +852,7 @@ class Subroutine(override val name: String,
}
class SubroutineParameter(val name: String, val register: Register?, val statusflag: Statusflag?) : Node {
data class SubroutineParameter(val name: String, val register: Register?, val statusflag: Statusflag?) : Node {
override var position: Position? = null
override lateinit var parent: Node
@ -859,7 +862,7 @@ class SubroutineParameter(val name: String, val register: Register?, val statusf
}
class SubroutineReturnvalue(val register: Register?, val statusflag: Statusflag?, val clobbered: Boolean) : Node {
data class SubroutineReturnvalue(val register: Register?, val statusflag: Statusflag?, val clobbered: Boolean) : Node {
override var position: Position? = null
override lateinit var parent: Node

View File

@ -1,5 +1,6 @@
package il65.ast
import il65.compiler.CompilationOptions
import il65.functions.BuiltIns
import il65.parser.ParsingFailedError
@ -7,8 +8,8 @@ import il65.parser.ParsingFailedError
* General checks on the Ast
*/
fun Module.checkValid(globalNamespace: INameScope) {
val checker = AstChecker(globalNamespace)
fun Module.checkValid(globalNamespace: INameScope, compilerOptions: CompilationOptions) {
val checker = AstChecker(globalNamespace, compilerOptions)
this.process(checker)
val checkResult = checker.result()
checkResult.forEach {
@ -24,7 +25,7 @@ fun Module.checkValid(globalNamespace: INameScope) {
* todo check subroutine return values against the call's result assignments
*/
class AstChecker(private val globalNamespace: INameScope) : IAstProcessor {
class AstChecker(private val globalNamespace: INameScope, val compilerOptions: CompilationOptions) : IAstProcessor {
private val checkResult: MutableList<SyntaxError> = mutableListOf()
fun result(): List<SyntaxError> {
@ -121,6 +122,10 @@ class AstChecker(private val globalNamespace: INameScope) : IAstProcessor {
err("recursive var declaration")
}
if(!compilerOptions.floats && decl.datatype==DataType.FLOAT) {
err("float var/const declaration, but floating point is not enabled via options")
}
when(decl.type) {
VarDeclType.VAR, VarDeclType.CONST -> {
when {
@ -233,6 +238,13 @@ class AstChecker(private val globalNamespace: INameScope) : IAstProcessor {
return super.process(directive)
}
override fun process(literalValue: LiteralValue): LiteralValue {
if(!compilerOptions.floats && literalValue.isFloat) {
checkResult.add(SyntaxError("floating point value used, but floating point is not enabled via options", literalValue.position))
}
return super.process(literalValue)
}
private fun checkConstInitializerValueArray(decl: VarDecl) {
val value = decl.value as LiteralValue
// init value should either be a scalar or an array with the same dimensions as the arrayspec.

View File

@ -89,10 +89,6 @@ data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, va
class Compiler(private val options: CompilationOptions, val namespace: INameScope) {
init {
val zeropage = Zeropage(options)
}
fun compile(module: Module) : IntermediateForm {
println("\nCompiling parsed source code to intermediate code...")
// todo