mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-02 12:50:55 +00:00
imports are now python style with a twist: forms! import std ffi and import local myfile
This commit is contained in:
parent
0e4362eefb
commit
81296ee1d1
@ -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:
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import "c.pork"
|
||||
import local c
|
||||
|
||||
export func b() {
|
||||
c()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import "a.pork"
|
||||
import local a
|
||||
|
||||
export func c() {
|
||||
a()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import "b.pork"
|
||||
import local b
|
||||
|
||||
export func d() {
|
||||
b()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import "d.pork"
|
||||
import local d
|
||||
|
||||
export func main() {
|
||||
d()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import std "ffi/malloc.pork"
|
||||
import std ffi.malloc
|
||||
|
||||
export func main() {
|
||||
while true {
|
||||
|
@ -1,5 +0,0 @@
|
||||
import "module.pork"
|
||||
|
||||
export func main() {
|
||||
hello()
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
export func main() {
|
||||
while true {
|
||||
println("Hello World")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
export func hello() {
|
||||
println("Hello World")
|
||||
}
|
@ -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 {
|
@ -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)
|
||||
|
@ -1,7 +1,5 @@
|
||||
package gay.pizza.pork.frontend
|
||||
|
||||
interface ImportSource {
|
||||
val fileContentSource: ContentSource
|
||||
|
||||
fun provideContentSource(form: String): ContentSource
|
||||
}
|
||||
|
@ -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}]"
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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),
|
||||
|
@ -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())
|
||||
|
@ -1 +1,2 @@
|
||||
numbers.pork
|
||||
ffi/malloc.pork
|
||||
numerics/operator.pork
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user