diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt index 943b1e236..dd574607b 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt @@ -33,7 +33,7 @@ internal class ProgramAndVarsGen( private val zeropage: Zeropage ) { private val compTarget = options.compTarget - private val callGraph = CallGraph(program) + private val callGraph = CallGraph(program, true) private val blockVariableInitializers = program.allBlocks.associateWith { it.statements.filterIsInstance() } internal fun generate() { diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 41430d283..626e46c45 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -3,12 +3,15 @@ package prog8.compiler import com.github.michaelbull.result.onFailure import prog8.ast.AstToSourceTextConverter import prog8.ast.IBuiltinFunctions +import prog8.ast.IStatementContainer import prog8.ast.Program import prog8.ast.base.AstException import prog8.ast.base.Position import prog8.ast.expressions.Expression import prog8.ast.expressions.NumericLiteralValue import prog8.ast.statements.Directive +import prog8.ast.statements.VarDecl +import prog8.ast.walk.IAstVisitor import prog8.codegen.target.C128Target import prog8.codegen.target.C64Target import prog8.codegen.target.Cx16Target @@ -348,6 +351,12 @@ private fun writeAssembly(program: Program, program.processAstBeforeAsmGeneration(compilerOptions, variables, errors) errors.report() + // TODO make removing all VarDecls work, but this needs inferType to be able to get its information from somewhere else as the VarDecl nodes in the Ast, + // or don't use inferType at all anymore and "bake the type information" into the Ast somehow. + // Note: we don't actually *need* to remove the VarDecl nodes, but it is nice as a temporary measure + // to help clean up the code that still depends on them. + // removeAllVardeclsFromAst(program) + // println("*********** AST RIGHT BEFORE ASM GENERATION *************") // printProgram(program) @@ -364,6 +373,26 @@ private fun writeAssembly(program: Program, } } +private fun removeAllVardeclsFromAst(program: Program) { + // remove all VarDecl nodes from the AST. + // code generation doesn't require them anymore, it operates only on the 'variables' collection. + + class SearchAndRemove: IAstVisitor { + private val allVars = mutableListOf() + init { + visit(program) + for (it in allVars) { + require((it.parent as IStatementContainer).statements.remove(it)) + } + } + override fun visit(decl: VarDecl) { + allVars.add(decl) + } + } + + SearchAndRemove() +} + fun printProgram(program: Program) { println() val printer = AstToSourceTextConverter(::print, program) diff --git a/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt b/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt index bee701cda..112776668 100644 --- a/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt +++ b/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt @@ -55,9 +55,6 @@ internal class BeforeAsmAstChanger(val program: Program, throw FatalAstException("vardecls for variables, with initial numerical value, should have been rewritten as plain vardecl + assignment $decl") } - // TODO get rid of the vardecl inside the ast - codegen should depend on the IVariableAllocation object - // but if we do this now, all variable name lookups break because these are still done on the Ast directly rather than on a separate symbol table - // return listOf(IAstModification.Remove(decl, parent as IStatementContainer)) return noModifications } diff --git a/compilerInterfaces/src/prog8/compilerinterface/CallGraph.kt b/compilerInterfaces/src/prog8/compilerinterface/CallGraph.kt index 9cc31be28..a4edf105c 100644 --- a/compilerInterfaces/src/prog8/compilerinterface/CallGraph.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/CallGraph.kt @@ -3,13 +3,14 @@ package prog8.compilerinterface import prog8.ast.Module import prog8.ast.Node import prog8.ast.Program +import prog8.ast.base.FatalAstException import prog8.ast.base.VarDeclType import prog8.ast.expressions.* import prog8.ast.statements.* import prog8.ast.walk.IAstVisitor -class CallGraph(private val program: Program) : IAstVisitor { +class CallGraph(private val program: Program, private val allowMissingIdentifierTargetVarDecls: Boolean=false) : IAstVisitor { val imports = mutableMapOf>().withDefault { setOf() } val importedBy = mutableMapOf>().withDefault { setOf() } @@ -109,7 +110,16 @@ class CallGraph(private val program: Program) : IAstVisitor { } override fun visit(identifier: IdentifierReference) { - allIdentifiersAndTargets[identifier] = identifier.targetStatement(program)!! + val target = identifier.targetStatement(program) + if(allowMissingIdentifierTargetVarDecls) { + if(target!=null) + allIdentifiersAndTargets[identifier] = target + } else { + if(target==null) + throw FatalAstException("missing target stmt for $identifier") + else + allIdentifiersAndTargets[identifier] = target + } } override fun visit(inlineAssembly: InlineAssembly) {