Split out all code into modules.

This commit is contained in:
2023-09-04 01:56:24 -07:00
parent d46ea1e307
commit 128f40bcf4
53 changed files with 119 additions and 81 deletions

31
tool/build.gradle.kts Normal file
View File

@ -0,0 +1,31 @@
plugins {
application
pork_module
id("com.github.johnrengelman.shadow") version "8.1.1"
id("org.graalvm.buildtools.native") version "0.9.25"
}
dependencies {
api(project(":ast"))
api(project(":parser"))
api(project(":frontend"))
api(project(":evaluator"))
implementation(libs.clikt)
implementation(project(":common"))
}
application {
mainClass.set("gay.pizza.pork.tool.MainKt")
}
graalvmNative {
binaries {
named("main") {
imageName.set("pork")
mainClass.set("gay.pizza.pork.tool.MainKt")
sharedLibrary.set(false)
}
}
}
tasks.run.get().outputs.upToDateWhen { false }

View File

@ -0,0 +1,24 @@
package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.types.path
import gay.pizza.pork.ast.Node
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
@OptIn(ExperimentalSerializationApi::class)
class AstCommand : CliktCommand(help = "Print AST", name = "ast") {
val path by argument("file").path(mustExist = true, canBeDir = false)
private val json = Json {
prettyPrint = true
prettyPrintIndent = " "
classDiscriminator = "\$"
}
override fun run() {
val tool = FileTool(path)
println(json.encodeToString(Node.serializer(), tool.parse()))
}
}

View File

@ -0,0 +1,26 @@
package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.types.path
import gay.pizza.pork.ast.NodeCoalescer
import gay.pizza.pork.parser.TokenNodeAttribution
class AttributeCommand : CliktCommand(help = "Attribute AST", name = "attribute") {
val path by argument("file").path(mustExist = true, canBeDir = false)
override fun run() {
val tool = FileTool(path)
val attribution = TokenNodeAttribution()
val compilationUnit = tool.parse(attribution)
val coalescer = NodeCoalescer { node ->
val tokens = attribution.assembleTokens(node)
println("node ${node.toString().replace("\n", "^")}")
for (token in tokens) {
println("token $token")
}
}
coalescer.visit(compilationUnit)
}
}

View File

@ -0,0 +1,13 @@
package gay.pizza.pork.tool
import gay.pizza.pork.frontend.ContentSource
import gay.pizza.pork.frontend.FsContentSource
import gay.pizza.pork.parser.StringCharSource
import java.nio.file.Path
import kotlin.io.path.readText
class FileTool(val path: Path) : Tool() {
override fun createCharSource(): gay.pizza.pork.parser.CharSource = StringCharSource(path.readText())
override fun createContentSource(): ContentSource = FsContentSource(path.parent)
override fun rootFilePath(): String = path.fileName.toString()
}

View File

@ -0,0 +1,14 @@
package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.types.path
class HighlightCommand : CliktCommand(help = "Syntax Highlighter", name = "highlight") {
val path by argument("file").path(mustExist = true, canBeDir = false)
override fun run() {
val tool = FileTool(path)
print(tool.highlight(gay.pizza.pork.parser.AnsiHighlightScheme()).joinToString(""))
}
}

View File

@ -0,0 +1,14 @@
package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.types.path
class ReprintCommand : CliktCommand(help = "Reprint Parsed Compilation Unit", name = "reprint") {
val path by argument("file").path(mustExist = true, canBeDir = false)
override fun run() {
val tool = FileTool(path)
print(tool.reprint())
}
}

View File

@ -0,0 +1,22 @@
package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.subcommands
class RootCommand : CliktCommand(
help = "Pork - The BBQ Language",
name = "pork"
) {
init {
subcommands(
RunCommand(),
HighlightCommand(),
TokenizeCommand(),
ReprintCommand(),
AstCommand(),
AttributeCommand()
)
}
override fun run() {}
}

View File

@ -0,0 +1,22 @@
package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.types.path
import gay.pizza.pork.evaluator.CallableFunction
import gay.pizza.pork.evaluator.Scope
class RunCommand : CliktCommand(help = "Run Program", name = "run") {
val path by argument("file").path(mustExist = true, canBeDir = false)
override fun run() {
val tool = FileTool(path)
val scope = Scope()
scope.define("println", CallableFunction { arguments ->
for (argument in arguments.values) {
println(argument)
}
})
tool.evaluate(scope)
}
}

View File

@ -0,0 +1,22 @@
package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.types.path
class TokenizeCommand : CliktCommand(help = "Tokenize Compilation Unit", name = "tokenize") {
val path by argument("file").path(mustExist = true, canBeDir = false)
override fun run() {
val tool = FileTool(path)
val tokenStream = tool.tokenize()
for (token in tokenStream.tokens) {
println("${token.start} ${token.type.name} '${sanitize(token.text)}'")
}
}
private fun sanitize(input: String): String =
input
.replace("\n", "\\n")
.replace("\r", "\\r")
}

View File

@ -0,0 +1,38 @@
package gay.pizza.pork.tool
import gay.pizza.pork.ast.NodeVisitor
import gay.pizza.pork.parser.Printer
import gay.pizza.pork.ast.CompilationUnit
import gay.pizza.pork.evaluator.Arguments
import gay.pizza.pork.evaluator.Evaluator
import gay.pizza.pork.evaluator.Scope
import gay.pizza.pork.frontend.ContentSource
import gay.pizza.pork.frontend.World
import gay.pizza.pork.parser.*
abstract class Tool {
abstract fun createCharSource(): CharSource
abstract fun createContentSource(): ContentSource
abstract fun rootFilePath(): String
fun tokenize(): TokenStream =
Tokenizer(createCharSource()).tokenize()
fun parse(attribution: NodeAttribution = DiscardNodeAttribution): CompilationUnit =
Parser(TokenStreamSource(tokenize()), attribution).readCompilationUnit()
fun highlight(scheme: HighlightScheme): List<Highlight> =
Highlighter(scheme).highlight(tokenize())
fun reprint(): String = buildString { visit(Printer(this)) }
fun <T> visit(visitor: NodeVisitor<T>): T = visitor.visit(parse())
fun evaluate(scope: Scope) {
val contentSource = createContentSource()
val world = World(contentSource)
val evaluator = Evaluator(world, scope)
val resultingScope = evaluator.evaluate(rootFilePath())
resultingScope.call("main", Arguments(emptyList()))
}
}

View File

@ -0,0 +1,3 @@
package gay.pizza.pork.tool
fun main(args: Array<String>) = RootCommand().main(args)