add a standard library, and introduce formed imports (import std "myfile.pork")

This commit is contained in:
2023-09-06 21:39:57 -07:00
parent f31e12df89
commit 0e4362eefb
18 changed files with 153 additions and 32 deletions

View File

@ -0,0 +1,3 @@
package gay.pizza.pork.frontend
data class ImportLocator(val path: String, val form: String? = null)

View File

@ -0,0 +1,7 @@
package gay.pizza.pork.frontend
interface ImportSource {
val fileContentSource: ContentSource
fun provideContentSource(form: String): ContentSource
}

View File

@ -0,0 +1,14 @@
package gay.pizza.pork.frontend
class StandardImportSource(override val fileContentSource: ContentSource) : ImportSource {
private val providers = mutableMapOf<String,ContentSource>()
override fun provideContentSource(form: String): ContentSource {
return providers[form] ?:
throw RuntimeException("Unknown import form: $form")
}
fun addContentSource(form: String, contentSource: ContentSource) {
providers[form] = contentSource
}
}

View File

@ -7,37 +7,57 @@ import gay.pizza.pork.parser.Parser
import gay.pizza.pork.parser.TokenStreamSource
import gay.pizza.pork.parser.Tokenizer
class World(val contentSource: ContentSource) {
class World(val importSource: ImportSource) {
private val internalUnits = mutableMapOf<String, CompilationUnit>()
val units: List<CompilationUnit>
get() = internalUnits.values.toList()
private fun loadOneUnit(path: String): CompilationUnit {
val stableIdentity = contentSource.stableContentIdentity(path)
val cached = internalUnits[stableIdentity]
private fun loadOneUnit(importLocator: ImportLocator): CompilationUnit {
val contentSource = pickContentSource(importLocator.form)
val stableKey = stableIdentity(importLocator, contentSource = contentSource)
val cached = internalUnits[stableKey]
if (cached != null) {
return cached
}
val charSource = contentSource.loadAsCharSource(path)
val charSource = contentSource.loadAsCharSource(importLocator.path)
val tokenizer = Tokenizer(charSource)
val tokenStream = tokenizer.tokenize()
val parser = Parser(TokenStreamSource(tokenStream), DiscardNodeAttribution)
return parser.readCompilationUnit()
val unit = parser.readCompilationUnit()
internalUnits[stableKey] = unit
return unit
}
private fun resolveAllImports(unit: CompilationUnit): Set<CompilationUnit> {
val units = mutableSetOf<CompilationUnit>()
for (declaration in unit.declarations.filterIsInstance<ImportDeclaration>()) {
val importedUnit = loadOneUnit(declaration.path.text)
val importLocator = ImportLocator(declaration.path.text, form = declaration.form?.id)
val importedUnit = loadOneUnit(importLocator)
units.add(importedUnit)
}
return units
}
fun load(path: String): CompilationUnit {
val unit = loadOneUnit(path)
fun load(importLocator: ImportLocator): CompilationUnit {
val unit = loadOneUnit(importLocator)
resolveAllImports(unit)
return unit
}
private fun pickContentSource(form: String? = null): ContentSource {
if (form != null) {
return importSource.provideContentSource(form)
}
return importSource.fileContentSource
}
fun stableIdentity(
importLocator: ImportLocator,
contentSource: ContentSource = pickContentSource(importLocator.form)
): String {
val formKey = importLocator.form ?: "file"
val stableIdentity = contentSource.stableContentIdentity(importLocator.path)
return "[${formKey}][${stableIdentity}]"
}
}