mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-02 21:00:56 +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
|
parent: Declaration
|
||||||
values:
|
values:
|
||||||
- name: form
|
- name: form
|
||||||
type: Symbol?
|
type: Symbol
|
||||||
- name: path
|
- name: components
|
||||||
type: StringLiteral
|
type: List<Symbol>
|
||||||
IntLiteral:
|
IntLiteral:
|
||||||
parent: Expression
|
parent: Expression
|
||||||
values:
|
values:
|
||||||
|
@ -6,23 +6,23 @@ import kotlinx.serialization.Serializable
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("importDeclaration")
|
@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 val type: NodeType = NodeType.ImportDeclaration
|
||||||
|
|
||||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
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 =
|
override fun <T> visit(visitor: NodeVisitor<T>): T =
|
||||||
visitor.visitImportDeclaration(this)
|
visitor.visitImportDeclaration(this)
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (other !is ImportDeclaration) return false
|
if (other !is ImportDeclaration) return false
|
||||||
return other.form == form && other.path == path
|
return other.form == form && other.components == components
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
var result = form.hashCode()
|
var result = form.hashCode()
|
||||||
result = 31 * result + path.hashCode()
|
result = 31 * result + components.hashCode()
|
||||||
result = 31 * result + type.hashCode()
|
result = 31 * result + type.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,8 @@ class CompilationUnitContext(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun processImport(import: ImportDeclaration) {
|
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)
|
val evaluationContext = evaluator.context(importLocator)
|
||||||
internalScope.inherit(evaluationContext.externalScope)
|
internalScope.inherit(evaluationContext.externalScope)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import "c.pork"
|
import local c
|
||||||
|
|
||||||
export func b() {
|
export func b() {
|
||||||
c()
|
c()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import "a.pork"
|
import local a
|
||||||
|
|
||||||
export func c() {
|
export func c() {
|
||||||
a()
|
a()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import "b.pork"
|
import local b
|
||||||
|
|
||||||
export func d() {
|
export func d() {
|
||||||
b()
|
b()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import "d.pork"
|
import local d
|
||||||
|
|
||||||
export func main() {
|
export func main() {
|
||||||
d()
|
d()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import std "ffi/malloc.pork"
|
import std ffi.malloc
|
||||||
|
|
||||||
export func main() {
|
export func main() {
|
||||||
while true {
|
while true {
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
import "module.pork"
|
|
||||||
|
|
||||||
export func main() {
|
|
||||||
hello()
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
export func main() {
|
export func main() {
|
||||||
while true {
|
while true {
|
||||||
println("Hello World")
|
println("Hello World")
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
export func hello() {
|
|
||||||
println("Hello World")
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
package gay.pizza.pork.frontend
|
package gay.pizza.pork.frontend
|
||||||
|
|
||||||
class StandardImportSource(override val fileContentSource: ContentSource) : ImportSource {
|
class DynamicImportSource : ImportSource {
|
||||||
private val providers = mutableMapOf<String,ContentSource>()
|
private val providers = mutableMapOf<String,ContentSource>()
|
||||||
|
|
||||||
override fun provideContentSource(form: String): ContentSource {
|
override fun provideContentSource(form: String): ContentSource {
|
@ -1,3 +1,3 @@
|
|||||||
package gay.pizza.pork.frontend
|
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
|
package gay.pizza.pork.frontend
|
||||||
|
|
||||||
interface ImportSource {
|
interface ImportSource {
|
||||||
val fileContentSource: ContentSource
|
|
||||||
|
|
||||||
fun provideContentSource(form: String): ContentSource
|
fun provideContentSource(form: String): ContentSource
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,8 @@ class World(val importSource: ImportSource) {
|
|||||||
private fun resolveAllImports(unit: CompilationUnit): Set<CompilationUnit> {
|
private fun resolveAllImports(unit: CompilationUnit): Set<CompilationUnit> {
|
||||||
val units = mutableSetOf<CompilationUnit>()
|
val units = mutableSetOf<CompilationUnit>()
|
||||||
for (declaration in unit.declarations.filterIsInstance<ImportDeclaration>()) {
|
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)
|
val importedUnit = loadOneUnit(importLocator)
|
||||||
units.add(importedUnit)
|
units.add(importedUnit)
|
||||||
}
|
}
|
||||||
@ -45,18 +46,14 @@ class World(val importSource: ImportSource) {
|
|||||||
return unit
|
return unit
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pickContentSource(form: String? = null): ContentSource {
|
private fun pickContentSource(form: String): ContentSource =
|
||||||
if (form != null) {
|
importSource.provideContentSource(form)
|
||||||
return importSource.provideContentSource(form)
|
|
||||||
}
|
|
||||||
return importSource.fileContentSource
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stableIdentity(
|
fun stableIdentity(
|
||||||
importLocator: ImportLocator,
|
importLocator: ImportLocator,
|
||||||
contentSource: ContentSource = pickContentSource(importLocator.form)
|
contentSource: ContentSource = pickContentSource(importLocator.form)
|
||||||
): String {
|
): String {
|
||||||
val formKey = importLocator.form ?: "file"
|
val formKey = importLocator.form
|
||||||
val stableIdentity = contentSource.stableContentIdentity(importLocator.path)
|
val stableIdentity = contentSource.stableContentIdentity(importLocator.path)
|
||||||
return "[${formKey}][${stableIdentity}]"
|
return "[${formKey}][${stableIdentity}]"
|
||||||
}
|
}
|
||||||
|
@ -183,11 +183,9 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
|
|
||||||
private fun readImportDeclaration(): ImportDeclaration = within {
|
private fun readImportDeclaration(): ImportDeclaration = within {
|
||||||
expect(TokenType.Import)
|
expect(TokenType.Import)
|
||||||
var form: Symbol? = null
|
val form = readSymbolRaw()
|
||||||
if (peek(TokenType.Symbol)) {
|
val components = oneAndContinuedBy(TokenType.Period) { readSymbolRaw() }
|
||||||
form = readSymbolRaw()
|
ImportDeclaration(form, components)
|
||||||
}
|
|
||||||
ImportDeclaration(form, readStringLiteral())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readFunctionDeclaration(): FunctionDefinition = within {
|
private fun readFunctionDeclaration(): FunctionDefinition = within {
|
||||||
@ -292,11 +290,21 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
): List<T> {
|
): List<T> {
|
||||||
val items = mutableListOf<T>()
|
val items = mutableListOf<T>()
|
||||||
while (!peek(peeking)) {
|
while (!peek(peeking)) {
|
||||||
val expression = read()
|
val item = read()
|
||||||
if (consuming != null) {
|
if (consuming != null) {
|
||||||
next(consuming)
|
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
|
return items
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,14 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
|
|||||||
|
|
||||||
override fun visitImportDeclaration(node: ImportDeclaration) {
|
override fun visitImportDeclaration(node: ImportDeclaration) {
|
||||||
append("import ")
|
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) {
|
override fun visitCompilationUnit(node: CompilationUnit) {
|
||||||
|
@ -22,6 +22,7 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
|||||||
RightParentheses(SingleChar(')')),
|
RightParentheses(SingleChar(')')),
|
||||||
Negation(SingleChar('!'), Promotion('=', Inequality), OperatorFamily),
|
Negation(SingleChar('!'), Promotion('=', Inequality), OperatorFamily),
|
||||||
Comma(SingleChar(',')),
|
Comma(SingleChar(',')),
|
||||||
|
Period(SingleChar('.')),
|
||||||
False(Keyword("false"), KeywordFamily),
|
False(Keyword("false"), KeywordFamily),
|
||||||
True(Keyword("true"), KeywordFamily),
|
True(Keyword("true"), KeywordFamily),
|
||||||
If(Keyword("if"), KeywordFamily),
|
If(Keyword("if"), KeywordFamily),
|
||||||
|
@ -8,7 +8,7 @@ object PorkStdlib : ContentSource {
|
|||||||
private val stdlibClass = PorkStdlib::class.java
|
private val stdlibClass = PorkStdlib::class.java
|
||||||
|
|
||||||
private fun readManifestFiles(): List<String> {
|
private fun readManifestFiles(): List<String> {
|
||||||
val manifestContent = read("stdlib.manifest")
|
val manifestContent = read("stdlib.manifest", check = false)
|
||||||
return manifestContent.split("\n").filter { line ->
|
return manifestContent.split("\n").filter { line ->
|
||||||
val trimmed = line.trim()
|
val trimmed = line.trim()
|
||||||
trimmed.isNotEmpty() && !trimmed.startsWith("#")
|
trimmed.isNotEmpty() && !trimmed.startsWith("#")
|
||||||
@ -17,7 +17,10 @@ object PorkStdlib : ContentSource {
|
|||||||
|
|
||||||
val files: List<String> = readManifestFiles()
|
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}")
|
val stream = stdlibClass.getResourceAsStream("/pork/stdlib/${path}")
|
||||||
?: throw RuntimeException("Stdlib does not contain file '${path}'")
|
?: throw RuntimeException("Stdlib does not contain file '${path}'")
|
||||||
return String(stream.readAllBytes())
|
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.evaluator.Scope
|
||||||
import gay.pizza.pork.frontend.ContentSource
|
import gay.pizza.pork.frontend.ContentSource
|
||||||
import gay.pizza.pork.frontend.ImportLocator
|
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.frontend.World
|
||||||
import gay.pizza.pork.parser.*
|
import gay.pizza.pork.parser.*
|
||||||
import gay.pizza.pork.stdlib.PorkStdlib
|
import gay.pizza.pork.stdlib.PorkStdlib
|
||||||
@ -33,12 +33,13 @@ abstract class Tool {
|
|||||||
|
|
||||||
fun loadMainFunction(scope: Scope, setupEvaluator: Evaluator.() -> Unit = {}): CallableFunction {
|
fun loadMainFunction(scope: Scope, setupEvaluator: Evaluator.() -> Unit = {}): CallableFunction {
|
||||||
val fileContentSource = createContentSource()
|
val fileContentSource = createContentSource()
|
||||||
val standardImportSource = StandardImportSource(fileContentSource)
|
val dynamicImportSource = DynamicImportSource()
|
||||||
standardImportSource.addContentSource("std", PorkStdlib)
|
dynamicImportSource.addContentSource("std", PorkStdlib)
|
||||||
val world = World(standardImportSource)
|
dynamicImportSource.addContentSource("local", fileContentSource)
|
||||||
|
val world = World(dynamicImportSource)
|
||||||
val evaluator = Evaluator(world, scope)
|
val evaluator = Evaluator(world, scope)
|
||||||
setupEvaluator(evaluator)
|
setupEvaluator(evaluator)
|
||||||
val resultingScope = evaluator.evaluate(ImportLocator(rootFilePath()))
|
val resultingScope = evaluator.evaluate(ImportLocator("local", rootFilePath()))
|
||||||
return resultingScope.value("main") as CallableFunction
|
return resultingScope.value("main") as CallableFunction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user