mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 13:11:32 +00:00
frontend: implement basic scope analysis
This commit is contained in:
@ -9,6 +9,7 @@ import gay.pizza.pork.parser.Tokenizer
|
||||
|
||||
class World(val importSource: ImportSource) {
|
||||
private val internalUnits = mutableMapOf<String, CompilationUnit>()
|
||||
private val importedUnits = mutableMapOf<CompilationUnit, Set<CompilationUnit>>()
|
||||
|
||||
val units: List<CompilationUnit>
|
||||
get() = internalUnits.values.toList()
|
||||
@ -37,6 +38,7 @@ class World(val importSource: ImportSource) {
|
||||
val importedUnit = loadOneUnit(importLocator)
|
||||
units.add(importedUnit)
|
||||
}
|
||||
importedUnits[unit] = units
|
||||
return units
|
||||
}
|
||||
|
||||
@ -46,6 +48,9 @@ class World(val importSource: ImportSource) {
|
||||
return unit
|
||||
}
|
||||
|
||||
fun importedBy(unit: CompilationUnit): Set<CompilationUnit> =
|
||||
importedUnits[unit] ?: emptySet()
|
||||
|
||||
private fun pickContentSource(form: String): ContentSource =
|
||||
importSource.provideContentSource(form)
|
||||
|
||||
|
@ -0,0 +1,36 @@
|
||||
package gay.pizza.pork.frontend.scope
|
||||
|
||||
import gay.pizza.pork.ast.CompilationUnit
|
||||
import gay.pizza.pork.ast.Symbol
|
||||
|
||||
class CompilationUnitScope(val worldScope: WorldScope, val unit: CompilationUnit) {
|
||||
val externalSymbols = mutableSetOf<ScopeSymbol>()
|
||||
val internalSymbols = mutableSetOf<ScopeSymbol>()
|
||||
|
||||
fun index() {
|
||||
for (definition in unit.definitions) {
|
||||
val scopeSymbol = ScopeSymbol(unit, definition)
|
||||
if (definition.modifiers.export) {
|
||||
externalSymbols.add(scopeSymbol)
|
||||
}
|
||||
internalSymbols.add(scopeSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
fun findInternallyVisibleSymbols(): Set<VisibleScopeSymbol> {
|
||||
val allSymbols = mutableMapOf<Symbol, VisibleScopeSymbol>()
|
||||
val imports = worldScope.world.importedBy(unit)
|
||||
for (import in imports) {
|
||||
val scope = worldScope.index(import)
|
||||
for (importedSymbol in scope.externalSymbols) {
|
||||
allSymbols[importedSymbol.symbol] = VisibleScopeSymbol(unit, importedSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
for (internalSymbol in internalSymbols) {
|
||||
allSymbols[internalSymbol.symbol] = VisibleScopeSymbol(unit, internalSymbol)
|
||||
}
|
||||
|
||||
return allSymbols.values.toSet()
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package gay.pizza.pork.frontend.scope
|
||||
|
||||
import gay.pizza.pork.ast.Definition
|
||||
import gay.pizza.pork.ast.Node
|
||||
|
||||
class ScopeSymbol(
|
||||
val compilationUnit: Node,
|
||||
val definition: Definition
|
||||
) {
|
||||
val symbol = definition.symbol
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package gay.pizza.pork.frontend.scope
|
||||
|
||||
import gay.pizza.pork.ast.CompilationUnit
|
||||
|
||||
class VisibleScopeSymbol(val visibleToUnit: CompilationUnit, val scopeSymbol: ScopeSymbol) {
|
||||
val isInternalSymbol: Boolean
|
||||
get() = visibleToUnit == scopeSymbol.compilationUnit
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package gay.pizza.pork.frontend.scope
|
||||
|
||||
import gay.pizza.pork.ast.CompilationUnit
|
||||
import gay.pizza.pork.frontend.World
|
||||
|
||||
class WorldScope(val world: World) {
|
||||
private val compilationUnitScopes = mutableMapOf<CompilationUnit, CompilationUnitScope>()
|
||||
|
||||
fun indexAll() {
|
||||
for (unit in world.units) {
|
||||
index(unit)
|
||||
}
|
||||
}
|
||||
|
||||
fun index(unit: CompilationUnit): CompilationUnitScope =
|
||||
scope(unit).apply {
|
||||
index()
|
||||
}
|
||||
|
||||
fun scope(unit: CompilationUnit): CompilationUnitScope =
|
||||
compilationUnitScopes.computeIfAbsent(unit) {
|
||||
CompilationUnitScope(this, unit)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user