mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
got rid of old IVariablesAndConsts object
This commit is contained in:
parent
cf362c4a61
commit
067283834a
@ -24,14 +24,13 @@ internal const val subroutineFloatEvalResultVar2 = "prog8_float_eval_result2"
|
||||
class AsmGen(internal val program: Program,
|
||||
internal val errors: IErrorReporter,
|
||||
internal val symbolTable: SymbolTable,
|
||||
internal val variables: IVariablesAndConsts,
|
||||
internal val options: CompilationOptions): IAssemblyGenerator {
|
||||
|
||||
internal val optimizedByteMultiplications = setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40,50,80,100)
|
||||
internal val optimizedWordMultiplications = setOf(3,5,6,7,9,10,12,15,20,25,40,50,80,100,320,640)
|
||||
internal val loopEndLabels = ArrayDeque<String>()
|
||||
private val zeropage = options.compTarget.machine.zeropage
|
||||
private val allocator = VariableAllocator(variables, symbolTable, options, errors)
|
||||
private val allocator = VariableAllocator(symbolTable, options, errors)
|
||||
private val assemblyLines = mutableListOf<String>()
|
||||
private val breakpointLabels = mutableListOf<String>()
|
||||
private val forloopsAsmGen = ForLoopsAsmGen(program, this, zeropage)
|
||||
|
@ -25,7 +25,7 @@ internal class ProgramAndVarsGen(
|
||||
val program: Program,
|
||||
val options: CompilationOptions,
|
||||
val errors: IErrorReporter,
|
||||
private val symboltable: SymbolTable, // TODO stick this in Program
|
||||
private val symboltable: SymbolTable,
|
||||
private val functioncallAsmGen: FunctionCallAsmGen,
|
||||
private val asmgen: AsmGen,
|
||||
private val allocator: VariableAllocator,
|
||||
|
@ -11,8 +11,7 @@ import prog8.ast.statements.ZeropageWish
|
||||
import prog8.compilerinterface.*
|
||||
|
||||
|
||||
internal class VariableAllocator(private val vars: IVariablesAndConsts,
|
||||
private val symboltable: SymbolTable,
|
||||
internal class VariableAllocator(private val symboltable: SymbolTable,
|
||||
private val options: CompilationOptions,
|
||||
private val errors: IErrorReporter) {
|
||||
|
||||
@ -36,53 +35,19 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts,
|
||||
if(options.zeropage== ZeropageType.DONTUSE)
|
||||
return
|
||||
|
||||
val allVariablesOld = (
|
||||
vars.blockVars.asSequence().flatMap { it.value } +
|
||||
vars.subroutineVars.asSequence().flatMap { it.value }
|
||||
).toList()
|
||||
|
||||
val allVariables = collectAllVariables(symboltable)
|
||||
require(allVariables.size == allVariablesOld.size)
|
||||
require(allVariables.map{it.scopedName}.toSet()==allVariablesOld.map{it.scopedname}.toSet())
|
||||
|
||||
val numberOfAllocatableVariables = allVariablesOld.size
|
||||
val varsRequiringZp = allVariablesOld.filter { it.zp == ZeropageWish.REQUIRE_ZEROPAGE }
|
||||
val varsPreferringZp = allVariablesOld.filter { it.zp == ZeropageWish.PREFER_ZEROPAGE }
|
||||
val varsDontCare = allVariablesOld.filter { it.zp == ZeropageWish.DONTCARE }
|
||||
val numberOfExplicitNonZpVariables = allVariablesOld.count { it.zp == ZeropageWish.NOT_IN_ZEROPAGE }
|
||||
val numberOfAllocatableVariables = allVariables.size
|
||||
val varsRequiringZp = allVariables.filter { it.zpw == ZeropageWish.REQUIRE_ZEROPAGE }
|
||||
val varsPreferringZp = allVariables.filter { it.zpw == ZeropageWish.PREFER_ZEROPAGE }
|
||||
val varsDontCare = allVariables.filter { it.zpw == ZeropageWish.DONTCARE }
|
||||
val numberOfExplicitNonZpVariables = allVariables.count { it.zpw == ZeropageWish.NOT_IN_ZEROPAGE }
|
||||
require(varsDontCare.size + varsRequiringZp.size + varsPreferringZp.size + numberOfExplicitNonZpVariables == numberOfAllocatableVariables)
|
||||
|
||||
val numberOfAllocatableVariables2 = allVariables.size
|
||||
val varsRequiringZp2 = allVariables.filter { it.zpw == ZeropageWish.REQUIRE_ZEROPAGE }
|
||||
val varsPreferringZp2 = allVariables.filter { it.zpw == ZeropageWish.PREFER_ZEROPAGE }
|
||||
val varsDontCare2 = allVariables.filter { it.zpw == ZeropageWish.DONTCARE }
|
||||
val numberOfExplicitNonZpVariables2 = allVariables.count { it.zpw == ZeropageWish.NOT_IN_ZEROPAGE }
|
||||
require(varsDontCare2.size + varsRequiringZp2.size + varsPreferringZp2.size + numberOfExplicitNonZpVariables2 == numberOfAllocatableVariables2)
|
||||
require(varsDontCare2.size==varsDontCare.size)
|
||||
require(varsRequiringZp2.size==varsRequiringZp.size)
|
||||
require(varsPreferringZp2.size==varsPreferringZp.size)
|
||||
require(numberOfExplicitNonZpVariables2==numberOfExplicitNonZpVariables)
|
||||
require(numberOfAllocatableVariables2==numberOfAllocatableVariables)
|
||||
|
||||
val oldvarsByName = varsDontCare.associateBy { it.scopedname }
|
||||
val newvarsByName = varsDontCare2.associateBy { it.scopedName }
|
||||
require(oldvarsByName.keys==newvarsByName.keys)
|
||||
oldvarsByName.forEach { (name, oldvar) ->
|
||||
val newvar = newvarsByName.getValue(name)
|
||||
require(oldvar.scopedname==newvar.scopedName)
|
||||
require(oldvar.type==newvar.dt)
|
||||
require(oldvar.zp==newvar.zpw)
|
||||
require(oldvar.initialValue==newvar.initialvalue)
|
||||
require(oldvar.arraysize==newvar.arraysize)
|
||||
require(oldvar.position==newvar.position)
|
||||
require(numArrayElements(oldvar) == numArrayElements(newvar))
|
||||
}
|
||||
|
||||
|
||||
var numVariablesAllocatedInZP = 0
|
||||
var numberOfNonIntegerVariables = 0
|
||||
|
||||
varsRequiringZp2.forEach { variable ->
|
||||
varsRequiringZp.forEach { variable ->
|
||||
val numElements = numArrayElements(variable)
|
||||
val result = zeropage.allocate(
|
||||
variable.scopedName,
|
||||
@ -103,7 +68,7 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts,
|
||||
}
|
||||
|
||||
if(errors.noErrors()) {
|
||||
varsPreferringZp2.forEach { variable ->
|
||||
varsPreferringZp.forEach { variable ->
|
||||
val numElements = numArrayElements(variable)
|
||||
val result = zeropage.allocate(
|
||||
variable.scopedName,
|
||||
@ -120,7 +85,7 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts,
|
||||
// try to allocate any other interger variables into the zeropage until it is full.
|
||||
// TODO some form of intelligent priorization? most often used variables first? loopcounter vars first? ...?
|
||||
if(errors.noErrors()) {
|
||||
for (variable in varsDontCare2.sortedWith(compareBy({it.scopedName.size}, {it.name}))) {
|
||||
for (variable in varsDontCare.sortedBy { it.scopedName.size }) {
|
||||
if(variable.dt in IntegerDatatypes) {
|
||||
if(zeropage.free.isEmpty()) {
|
||||
break
|
||||
@ -163,13 +128,6 @@ internal class VariableAllocator(private val vars: IVariablesAndConsts,
|
||||
|
||||
internal fun isZpVar(scopedName: List<String>) = scopedName in zeropage.allocatedVariables
|
||||
|
||||
private fun numArrayElements(variable: IVariablesAndConsts.StaticVariable) =
|
||||
when(variable.type) {
|
||||
DataType.STR -> (variable.initialValue as StringLiteral).value.length
|
||||
in ArrayDatatypes -> variable.arraysize!!
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun numArrayElements(variable: StStaticVariable) =
|
||||
when(variable.dt) {
|
||||
DataType.STR -> (variable.initialvalue as StringLiteral).value.length
|
||||
|
@ -6,7 +6,6 @@ import prog8.compilerinterface.*
|
||||
class AsmGen(internal val program: Program,
|
||||
internal val errors: IErrorReporter,
|
||||
internal val symbolTable: SymbolTable,
|
||||
internal val variables: IVariablesAndConsts,
|
||||
internal val options: CompilationOptions): IAssemblyGenerator {
|
||||
|
||||
override fun compileToAssembly(): IAssemblyProgram? {
|
||||
|
@ -363,7 +363,6 @@ private fun writeAssembly(program: Program,
|
||||
compilerOptions.compTarget.machine.initializeZeropage(compilerOptions)
|
||||
program.processAstBeforeAsmGeneration(compilerOptions, errors)
|
||||
errors.report()
|
||||
val variables = VariableExtractor().extractFrom(program)
|
||||
val symbolTable = SymbolTableMaker().makeFrom(program)
|
||||
|
||||
// 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,
|
||||
@ -375,7 +374,7 @@ private fun writeAssembly(program: Program,
|
||||
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
||||
// printProgram(program)
|
||||
|
||||
val assembly = asmGeneratorFor(program, errors, symbolTable, variables, compilerOptions).compileToAssembly()
|
||||
val assembly = asmGeneratorFor(program, errors, symbolTable, compilerOptions).compileToAssembly()
|
||||
errors.report()
|
||||
|
||||
return if(assembly!=null && errors.noErrors()) {
|
||||
@ -418,15 +417,14 @@ fun printProgram(program: Program) {
|
||||
internal fun asmGeneratorFor(program: Program,
|
||||
errors: IErrorReporter,
|
||||
symbolTable: SymbolTable,
|
||||
variables: IVariablesAndConsts,
|
||||
options: CompilationOptions): IAssemblyGenerator
|
||||
{
|
||||
if(options.experimentalCodegen) {
|
||||
if (options.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02))
|
||||
return prog8.codegen.experimental6502.AsmGen(program, errors, symbolTable, variables, options)
|
||||
return prog8.codegen.experimental6502.AsmGen(program, errors, symbolTable, options)
|
||||
} else {
|
||||
if (options.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02))
|
||||
return prog8.codegen.cpu6502.AsmGen(program, errors, symbolTable, variables, options)
|
||||
return prog8.codegen.cpu6502.AsmGen(program, errors, symbolTable, options)
|
||||
}
|
||||
|
||||
throw NotImplementedError("no asm generator for cpu ${options.compTarget.machine.cpu}")
|
||||
|
@ -1,183 +0,0 @@
|
||||
package prog8.compiler.astprocessing
|
||||
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.base.VarDeclType
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.statements.Block
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.ast.walk.IAstVisitor
|
||||
import prog8.compilerinterface.IVariablesAndConsts
|
||||
|
||||
|
||||
internal class VariableExtractor: IAstVisitor {
|
||||
private val allBlockVars = mutableMapOf<Block, MutableSet<VarDecl>>()
|
||||
private val allBlockConsts = mutableMapOf<Block, MutableSet<VarDecl>>()
|
||||
private val allBlockMemoryvars = mutableMapOf<Block, MutableSet<VarDecl>>()
|
||||
private val allSubroutineVars = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
|
||||
private val allSubroutineConsts = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
|
||||
private val allSubroutineMemoryvars = mutableMapOf<Subroutine, MutableSet<VarDecl>>()
|
||||
|
||||
fun extractFrom(program: Program): IVariablesAndConsts {
|
||||
this.visit(program)
|
||||
return VariablesAndConsts(
|
||||
allBlockVars, allBlockConsts, allBlockMemoryvars,
|
||||
allSubroutineVars, allSubroutineConsts, allSubroutineMemoryvars)
|
||||
}
|
||||
|
||||
override fun visit(decl: VarDecl) {
|
||||
val scope=decl.definingScope
|
||||
when (decl.type) {
|
||||
VarDeclType.VAR -> {
|
||||
when (scope) {
|
||||
is Block -> {
|
||||
val decls = allBlockVars[scope] ?: mutableSetOf()
|
||||
decls.add(decl)
|
||||
allBlockVars[scope] = decls
|
||||
}
|
||||
is Subroutine -> {
|
||||
val decls = allSubroutineVars[scope] ?: mutableSetOf()
|
||||
decls.add(decl)
|
||||
allSubroutineVars[scope] = decls
|
||||
}
|
||||
else -> {
|
||||
throw FatalAstException("var can only occur in subroutine or block scope")
|
||||
}
|
||||
}
|
||||
}
|
||||
VarDeclType.CONST -> {
|
||||
when(scope) {
|
||||
is Block -> {
|
||||
val decls = allBlockConsts[scope] ?: mutableSetOf()
|
||||
decls.add(decl)
|
||||
allBlockConsts[scope] = decls
|
||||
}
|
||||
is Subroutine -> {
|
||||
val decls = allSubroutineConsts[scope] ?: mutableSetOf()
|
||||
decls.add(decl)
|
||||
allSubroutineConsts[scope] = decls
|
||||
}
|
||||
else -> {
|
||||
throw FatalAstException("var can only occur in subroutine or block scope")
|
||||
}
|
||||
}
|
||||
}
|
||||
VarDeclType.MEMORY -> {
|
||||
when(scope) {
|
||||
is Block -> {
|
||||
val decls = allBlockMemoryvars[scope] ?: mutableSetOf()
|
||||
decls.add(decl)
|
||||
allBlockMemoryvars[scope] = decls
|
||||
}
|
||||
is Subroutine -> {
|
||||
val decls = allSubroutineMemoryvars[scope] ?: mutableSetOf()
|
||||
decls.add(decl)
|
||||
allSubroutineMemoryvars[scope] = decls
|
||||
}
|
||||
else -> {
|
||||
throw FatalAstException("var can only occur in subroutine or block scope")
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
throw FatalAstException("invalid var type")
|
||||
}
|
||||
}
|
||||
super.visit(decl)
|
||||
}
|
||||
}
|
||||
|
||||
internal class VariablesAndConsts (
|
||||
astBlockVars: Map<Block, Set<VarDecl>>,
|
||||
astBlockConsts: Map<Block, Set<VarDecl>>,
|
||||
astBlockMemvars: Map<Block, Set<VarDecl>>,
|
||||
astSubroutineVars: Map<Subroutine, Set<VarDecl>>,
|
||||
astSubroutineConsts: Map<Subroutine, Set<VarDecl>>,
|
||||
astSubroutineMemvars: Map<Subroutine, Set<VarDecl>>
|
||||
) : IVariablesAndConsts
|
||||
{
|
||||
override val blockVars: Map<Block, Set<IVariablesAndConsts.StaticVariable>>
|
||||
override val blockConsts: Map<Block, Set<IVariablesAndConsts.ConstantNumberSymbol>>
|
||||
override val blockMemvars: Map<Block, Set<IVariablesAndConsts.MemoryMappedVariable>>
|
||||
override val subroutineVars: Map<Subroutine, Set<IVariablesAndConsts.StaticVariable>>
|
||||
override val subroutineConsts: Map<Subroutine, Set<IVariablesAndConsts.ConstantNumberSymbol>>
|
||||
override val subroutineMemvars: Map<Subroutine, Set<IVariablesAndConsts.MemoryMappedVariable>>
|
||||
|
||||
private val bv = astBlockVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticVariable>() }
|
||||
private val bc = astBlockConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
|
||||
private val bmv = astBlockMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
|
||||
private val sv = astSubroutineVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticVariable>() }
|
||||
private val sc = astSubroutineConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
|
||||
private val smv = astSubroutineMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
|
||||
|
||||
init {
|
||||
astBlockVars.forEach { (block, decls) ->
|
||||
val vars = bv.getValue(block)
|
||||
vars.addAll(decls.map { toStatic(it) })
|
||||
}
|
||||
astBlockConsts.forEach { (block, decls) ->
|
||||
bc.getValue(block).addAll(
|
||||
decls.map {
|
||||
IVariablesAndConsts.ConstantNumberSymbol(
|
||||
it.datatype,
|
||||
it.scopedName,
|
||||
(it.value as NumericLiteral).number,
|
||||
it.position
|
||||
)
|
||||
})
|
||||
}
|
||||
astBlockMemvars.forEach { (block, decls) ->
|
||||
val vars = bmv.getValue(block)
|
||||
for(decl in decls) {
|
||||
// make sure the 'stubs' for the scratch variables in zeropage are not included as normal variables
|
||||
if(!decl.name.startsWith("P8ZP_SCRATCH_")) {
|
||||
vars.add(
|
||||
IVariablesAndConsts.MemoryMappedVariable(
|
||||
decl.datatype,
|
||||
decl.scopedName,
|
||||
(decl.value as NumericLiteral).number.toUInt(),
|
||||
decl.position
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
astSubroutineVars.forEach { (sub, decls) ->
|
||||
val vars = sv.getValue(sub)
|
||||
vars.addAll(decls.map { toStatic(it) })
|
||||
}
|
||||
astSubroutineConsts.forEach { (sub, decls) ->
|
||||
sc.getValue(sub).addAll(
|
||||
decls.map {
|
||||
IVariablesAndConsts.ConstantNumberSymbol(
|
||||
it.datatype,
|
||||
it.scopedName,
|
||||
(it.value as NumericLiteral).number,
|
||||
it.position
|
||||
)
|
||||
})
|
||||
}
|
||||
astSubroutineMemvars.forEach { (sub, decls) ->
|
||||
smv.getValue(sub).addAll(
|
||||
decls.map {
|
||||
IVariablesAndConsts.MemoryMappedVariable(
|
||||
it.datatype,
|
||||
it.scopedName,
|
||||
(it.value as NumericLiteral).number.toUInt(),
|
||||
it.position
|
||||
)
|
||||
})
|
||||
}
|
||||
blockVars = bv
|
||||
blockConsts = bc
|
||||
blockMemvars = bmv
|
||||
subroutineVars = sv
|
||||
subroutineConsts = sc
|
||||
subroutineMemvars = smv
|
||||
}
|
||||
|
||||
private fun toStatic(decl: VarDecl) =
|
||||
IVariablesAndConsts.StaticVariable(decl.datatype, decl.scopedName, decl.value, decl.arraysize?.constIndex(), decl.zeropage, decl.position)
|
||||
|
||||
}
|
@ -16,7 +16,6 @@ import prog8.ast.base.Position
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.codegen.target.C64Target
|
||||
import prog8.compiler.astprocessing.VariableExtractor
|
||||
import prog8.compiler.astprocessing.processAstBeforeAsmGeneration
|
||||
import prog8.compiler.printProgram
|
||||
import prog8.compilerinterface.CompilationOptions
|
||||
|
@ -16,7 +16,6 @@ import prog8.codegen.cpu6502.AsmGen
|
||||
import prog8.codegen.target.C64Target
|
||||
import prog8.codegen.target.c64.C64Zeropage
|
||||
import prog8.compiler.astprocessing.SymbolTableMaker
|
||||
import prog8.compiler.astprocessing.VariableExtractor
|
||||
import prog8.compilerinterface.*
|
||||
import prog8.parser.SourceCode
|
||||
import prog8tests.helpers.DummyFunctions
|
||||
@ -80,8 +79,7 @@ class TestAsmGenSymbols: StringSpec({
|
||||
val options = CompilationOptions(OutputType.RAW, CbmPrgLauncherType.NONE, ZeropageType.FULL, emptyList(), false, true, C64Target())
|
||||
options.compTarget.machine.zeropage = C64Zeropage(options)
|
||||
val st = SymbolTableMaker().makeFrom(program)
|
||||
val allocation = VariableExtractor().extractFrom(program)
|
||||
return AsmGen(program, errors, st, allocation, options)
|
||||
return AsmGen(program, errors, st, options)
|
||||
}
|
||||
|
||||
"symbol and variable names from strings" {
|
||||
|
@ -9,7 +9,6 @@ import prog8.codegen.target.c64.C64Zeropage
|
||||
import prog8.compiler.CompilationResult
|
||||
import prog8.compiler.CompilerArguments
|
||||
import prog8.compiler.astprocessing.SymbolTableMaker
|
||||
import prog8.compiler.astprocessing.VariableExtractor
|
||||
import prog8.compiler.compileProgram
|
||||
import prog8.compilerinterface.*
|
||||
import java.nio.file.Path
|
||||
@ -89,8 +88,7 @@ internal fun generateAssembly(
|
||||
): IAssemblyProgram? {
|
||||
val coptions = options ?: CompilationOptions(OutputType.RAW, CbmPrgLauncherType.BASIC, ZeropageType.DONTUSE, emptyList(), true, true, C64Target(), outputDir = outputDir)
|
||||
coptions.compTarget.machine.zeropage = C64Zeropage(coptions)
|
||||
val variables = VariableExtractor().extractFrom(program)
|
||||
val st = SymbolTableMaker().makeFrom(program)
|
||||
val asmgen = AsmGen(program, ErrorReporterForTests(), st, variables, coptions)
|
||||
val asmgen = AsmGen(program, ErrorReporterForTests(), st, coptions)
|
||||
return asmgen.compileToAssembly()
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
package prog8.compilerinterface
|
||||
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.base.Position
|
||||
import prog8.ast.expressions.Expression
|
||||
import prog8.ast.statements.Block
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.ast.statements.ZeropageWish
|
||||
|
||||
/**
|
||||
* A more convenient way to pass variable (and constant values) definitions to the code generator,
|
||||
* so that it doesn't have to scavenge and manipulate the VerDecl nodes in the AST for this information.
|
||||
*
|
||||
* note: the string variables are in here as well, they're in blockVars for the block named 'prog8_interned_strings'.
|
||||
*/
|
||||
|
||||
// TODO remove this, and replace with SymbolTable
|
||||
|
||||
interface IVariablesAndConsts {
|
||||
data class ConstantNumberSymbol(val type: DataType, val scopedname: List<String>, val value: Double, val position: Position)
|
||||
data class MemoryMappedVariable(val type: DataType, val scopedname: List<String>, val address: UInt, val position: Position)
|
||||
data class StaticVariable(val type: DataType,
|
||||
val scopedname: List<String>,
|
||||
val initialValue: Expression?,
|
||||
val arraysize: Int?,
|
||||
val zp: ZeropageWish,
|
||||
val position: Position)
|
||||
|
||||
val blockVars: Map<Block, Set<StaticVariable>>
|
||||
val blockConsts: Map<Block, Set<ConstantNumberSymbol>>
|
||||
val blockMemvars: Map<Block, Set<MemoryMappedVariable>>
|
||||
val subroutineVars: Map<Subroutine, Set<StaticVariable>>
|
||||
val subroutineConsts: Map<Subroutine, Set<ConstantNumberSymbol>>
|
||||
val subroutineMemvars: Map<Subroutine, Set<MemoryMappedVariable>>
|
||||
}
|
@ -8,6 +8,19 @@ import prog8.ast.statements.ZeropageWish
|
||||
import prog8.ast.toHex
|
||||
|
||||
|
||||
/**
|
||||
* Tree structure containing all symbol definitions in the program
|
||||
* (blocks, subroutines, variables (all types) and labels).
|
||||
*/
|
||||
class SymbolTable : StNode("", StNodeType.GLOBAL, Position.DUMMY) {
|
||||
fun print() = printIndented(0)
|
||||
|
||||
override fun printProperties() { }
|
||||
|
||||
val origAstLinks = mutableMapOf<Node, StNode>() // links of the original Ast nodes to the symbol table node.
|
||||
}
|
||||
|
||||
|
||||
enum class StNodeType {
|
||||
GLOBAL,
|
||||
// MODULE, // not used with current scoping rules
|
||||
@ -81,7 +94,7 @@ open class StNode(val name: String,
|
||||
}
|
||||
}
|
||||
|
||||
fun printIndented(indent: Int) {
|
||||
protected fun printIndented(indent: Int) {
|
||||
print(" ".repeat(indent))
|
||||
when(type) {
|
||||
StNodeType.GLOBAL -> print("SYMBOL-TABLE:")
|
||||
@ -108,14 +121,6 @@ open class StNode(val name: String,
|
||||
}
|
||||
}
|
||||
|
||||
class SymbolTable : StNode("", StNodeType.GLOBAL, Position.DUMMY) {
|
||||
fun print() = printIndented(0)
|
||||
|
||||
override fun printProperties() { }
|
||||
|
||||
val origAstLinks = mutableMapOf<Node, StNode>() // link the original Ast nodes into the table. TODO is this really needed?
|
||||
}
|
||||
|
||||
class StStaticVariable(name: String,
|
||||
val dt: DataType,
|
||||
val initialvalue: Expression?,
|
||||
|
Loading…
Reference in New Issue
Block a user