imports are now python style with a twist: forms! import std ffi and import local myfile

This commit is contained in:
Alex Zenla 2023-09-06 22:43:03 -07:00
parent 0e4362eefb
commit 81296ee1d1
Signed by: alex
GPG Key ID: C0780728420EBFE5
22 changed files with 58 additions and 50 deletions

View File

@ -111,9 +111,9 @@ types:
parent: Declaration
values:
- name: form
type: Symbol?
- name: path
type: StringLiteral
type: Symbol
- name: components
type: List<Symbol>
IntLiteral:
parent: Expression
values:

View File

@ -6,23 +6,23 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("importDeclaration")
class ImportDeclaration(val form: Symbol?, val path: StringLiteral) : Declaration() {
class ImportDeclaration(val form: Symbol, val components: List<Symbol>) : Declaration() {
override val type: NodeType = NodeType.ImportDeclaration
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
visitor.visitNodes(form, path)
visitor.visitAll(listOf(form), components)
override fun <T> visit(visitor: NodeVisitor<T>): T =
visitor.visitImportDeclaration(this)
override fun equals(other: Any?): Boolean {
if (other !is ImportDeclaration) return false
return other.form == form && other.path == path
return other.form == form && other.components == components
}
override fun hashCode(): Int {
var result = form.hashCode()
result = 31 * result + path.hashCode()
result = 31 * result + components.hashCode()
result = 31 * result + type.hashCode()
return result
}

View File

@ -51,7 +51,8 @@ class CompilationUnitContext(
}
private fun processImport(import: ImportDeclaration) {
val importLocator = ImportLocator(import.path.text, import.form?.id)
val importPath = import.components.joinToString("/") { it.id } + ".pork"
val importLocator = ImportLocator(import.form.id, importPath)
val evaluationContext = evaluator.context(importLocator)
internalScope.inherit(evaluationContext.externalScope)
}

View File

@ -1,4 +1,4 @@
import "c.pork"
import local c
export func b() {
c()

View File

@ -1,4 +1,4 @@
import "a.pork"
import local a
export func c() {
a()

View File

@ -1,4 +1,4 @@
import "b.pork"
import local b
export func d() {
b()

View File

@ -1,4 +1,4 @@
import "d.pork"
import local d
export func main() {
d()

View File

@ -1,4 +1,4 @@
import std "ffi/malloc.pork"
import std ffi.malloc
export func main() {
while true {

View File

@ -1,5 +0,0 @@
import "module.pork"
export func main() {
hello()
}

View File

@ -1,6 +1,5 @@
export func main() {
while true {
println("Hello World")
break
}
}

View File

@ -1,3 +0,0 @@
export func hello() {
println("Hello World")
}

View File

@ -1,6 +1,6 @@
package gay.pizza.pork.frontend
class StandardImportSource(override val fileContentSource: ContentSource) : ImportSource {
class DynamicImportSource : ImportSource {
private val providers = mutableMapOf<String,ContentSource>()
override fun provideContentSource(form: String): ContentSource {

View File

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

View File

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

View File

@ -32,7 +32,8 @@ class World(val importSource: ImportSource) {
private fun resolveAllImports(unit: CompilationUnit): Set<CompilationUnit> {
val units = mutableSetOf<CompilationUnit>()
for (declaration in unit.declarations.filterIsInstance<ImportDeclaration>()) {
val importLocator = ImportLocator(declaration.path.text, form = declaration.form?.id)
val importPath = declaration.components.joinToString("/") { it.id } + ".pork"
val importLocator = ImportLocator(declaration.form.id, importPath)
val importedUnit = loadOneUnit(importLocator)
units.add(importedUnit)
}
@ -45,18 +46,14 @@ class World(val importSource: ImportSource) {
return unit
}
private fun pickContentSource(form: String? = null): ContentSource {
if (form != null) {
return importSource.provideContentSource(form)
}
return importSource.fileContentSource
}
private fun pickContentSource(form: String): ContentSource =
importSource.provideContentSource(form)
fun stableIdentity(
importLocator: ImportLocator,
contentSource: ContentSource = pickContentSource(importLocator.form)
): String {
val formKey = importLocator.form ?: "file"
val formKey = importLocator.form
val stableIdentity = contentSource.stableContentIdentity(importLocator.path)
return "[${formKey}][${stableIdentity}]"
}

View File

@ -183,11 +183,9 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
private fun readImportDeclaration(): ImportDeclaration = within {
expect(TokenType.Import)
var form: Symbol? = null
if (peek(TokenType.Symbol)) {
form = readSymbolRaw()
}
ImportDeclaration(form, readStringLiteral())
val form = readSymbolRaw()
val components = oneAndContinuedBy(TokenType.Period) { readSymbolRaw() }
ImportDeclaration(form, components)
}
private fun readFunctionDeclaration(): FunctionDefinition = within {
@ -292,11 +290,21 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
): List<T> {
val items = mutableListOf<T>()
while (!peek(peeking)) {
val expression = read()
val item = read()
if (consuming != null) {
next(consuming)
}
items.add(expression)
items.add(item)
}
return items
}
private fun <T> oneAndContinuedBy(separator: TokenType, read: () -> T): List<T> {
val items = mutableListOf<T>()
items.add(read())
while (peek(separator)) {
expect(separator)
items.add(read())
}
return items
}

View File

@ -166,7 +166,14 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
override fun visitImportDeclaration(node: ImportDeclaration) {
append("import ")
visit(node.path)
visit(node.form)
append(" ")
for ((index, component) in node.components.withIndex()) {
visit(component)
if (index != node.components.size - 1) {
append(".")
}
}
}
override fun visitCompilationUnit(node: CompilationUnit) {

View File

@ -22,6 +22,7 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
RightParentheses(SingleChar(')')),
Negation(SingleChar('!'), Promotion('=', Inequality), OperatorFamily),
Comma(SingleChar(',')),
Period(SingleChar('.')),
False(Keyword("false"), KeywordFamily),
True(Keyword("true"), KeywordFamily),
If(Keyword("if"), KeywordFamily),

View File

@ -8,7 +8,7 @@ object PorkStdlib : ContentSource {
private val stdlibClass = PorkStdlib::class.java
private fun readManifestFiles(): List<String> {
val manifestContent = read("stdlib.manifest")
val manifestContent = read("stdlib.manifest", check = false)
return manifestContent.split("\n").filter { line ->
val trimmed = line.trim()
trimmed.isNotEmpty() && !trimmed.startsWith("#")
@ -17,7 +17,10 @@ object PorkStdlib : ContentSource {
val files: List<String> = readManifestFiles()
private fun read(path: String): String {
private fun read(path: String, check: Boolean = true): String {
if (check && !files.contains(path)) {
throw RuntimeException("Stdlib does not contain file '${path}'")
}
val stream = stdlibClass.getResourceAsStream("/pork/stdlib/${path}")
?: throw RuntimeException("Stdlib does not contain file '${path}'")
return String(stream.readAllBytes())

View File

@ -1 +1,2 @@
numbers.pork
ffi/malloc.pork
numerics/operator.pork

View File

@ -8,7 +8,7 @@ import gay.pizza.pork.evaluator.Evaluator
import gay.pizza.pork.evaluator.Scope
import gay.pizza.pork.frontend.ContentSource
import gay.pizza.pork.frontend.ImportLocator
import gay.pizza.pork.frontend.StandardImportSource
import gay.pizza.pork.frontend.DynamicImportSource
import gay.pizza.pork.frontend.World
import gay.pizza.pork.parser.*
import gay.pizza.pork.stdlib.PorkStdlib
@ -33,12 +33,13 @@ abstract class Tool {
fun loadMainFunction(scope: Scope, setupEvaluator: Evaluator.() -> Unit = {}): CallableFunction {
val fileContentSource = createContentSource()
val standardImportSource = StandardImportSource(fileContentSource)
standardImportSource.addContentSource("std", PorkStdlib)
val world = World(standardImportSource)
val dynamicImportSource = DynamicImportSource()
dynamicImportSource.addContentSource("std", PorkStdlib)
dynamicImportSource.addContentSource("local", fileContentSource)
val world = World(dynamicImportSource)
val evaluator = Evaluator(world, scope)
setupEvaluator(evaluator)
val resultingScope = evaluator.evaluate(ImportLocator(rootFilePath()))
val resultingScope = evaluator.evaluate(ImportLocator("local", rootFilePath()))
return resultingScope.value("main") as CallableFunction
}
}