Split out all code into modules.

This commit is contained in:
Alex Zenla 2023-09-04 01:56:24 -07:00
parent d46ea1e307
commit 128f40bcf4
Signed by: alex
GPG Key ID: C0780728420EBFE5
53 changed files with 119 additions and 81 deletions

View File

@ -23,5 +23,5 @@ fn main() {
## Usage ## Usage
``` ```
./gradlew -q core:run --args 'run ../examples/fib.pork' ./gradlew -q tool:run --args 'run ../examples/fib.pork'
``` ```

3
common/build.gradle.kts Normal file
View File

@ -0,0 +1,3 @@
plugins {
pork_module
}

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.util package gay.pizza.pork.common
class IndentPrinter( class IndentPrinter(
val buffer: StringBuilder = StringBuilder(), val buffer: StringBuilder = StringBuilder(),

View File

@ -1,3 +0,0 @@
package gay.pizza.pork
object PorkLanguage

View File

@ -1,3 +0,0 @@
package gay.pizza.pork.eval
data object None

View File

@ -0,0 +1,10 @@
plugins {
pork_module
}
dependencies {
api(project(":ast"))
api(project(":frontend"))
implementation(project(":common"))
}

View File

@ -1,3 +1,3 @@
package gay.pizza.pork.eval package gay.pizza.pork.evaluator
class Arguments(val values: List<Any>) class Arguments(val values: List<Any>)

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.eval package gay.pizza.pork.evaluator
fun interface BlockFunction { fun interface BlockFunction {
fun call(): Any fun call(): Any

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.eval package gay.pizza.pork.evaluator
fun interface CallableFunction { fun interface CallableFunction {
fun call(arguments: Arguments): Any fun call(arguments: Arguments): Any

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.eval package gay.pizza.pork.evaluator
import gay.pizza.pork.ast.CompilationUnit import gay.pizza.pork.ast.CompilationUnit
import gay.pizza.pork.ast.ImportDeclaration import gay.pizza.pork.ast.ImportDeclaration

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.eval package gay.pizza.pork.evaluator
interface EvaluationContextProvider { interface EvaluationContextProvider {
fun provideEvaluationContext(path: String): EvaluationContext fun provideEvaluationContext(path: String): EvaluationContext

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.eval package gay.pizza.pork.evaluator
import gay.pizza.pork.ast.* import gay.pizza.pork.ast.*

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.eval package gay.pizza.pork.evaluator
import gay.pizza.pork.frontend.World import gay.pizza.pork.frontend.World

View File

@ -0,0 +1,3 @@
package gay.pizza.pork.evaluator
data object None

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.eval package gay.pizza.pork.evaluator
class Scope(val parent: Scope? = null, inherits: List<Scope> = emptyList()) { class Scope(val parent: Scope? = null, inherits: List<Scope> = emptyList()) {
private val inherited = inherits.toMutableList() private val inherited = inherits.toMutableList()

10
frontend/build.gradle.kts Normal file
View File

@ -0,0 +1,10 @@
plugins {
pork_module
}
dependencies {
api(project(":ast"))
api(project(":parser"))
implementation(project(":common"))
}

View File

@ -1,6 +1,6 @@
package gay.pizza.pork.frontend package gay.pizza.pork.frontend
import gay.pizza.pork.parse.CharSource import gay.pizza.pork.parser.CharSource
interface ContentSource { interface ContentSource {
fun loadAsCharSource(path: String): CharSource fun loadAsCharSource(path: String): CharSource

View File

@ -1,13 +1,12 @@
package gay.pizza.pork.frontend package gay.pizza.pork.frontend
import gay.pizza.pork.parse.CharSource import gay.pizza.pork.parser.StringCharSource
import gay.pizza.pork.parse.StringCharSource
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.absolutePathString import kotlin.io.path.absolutePathString
import kotlin.io.path.readText import kotlin.io.path.readText
class FsContentSource(val root: Path) : ContentSource { class FsContentSource(val root: Path) : ContentSource {
override fun loadAsCharSource(path: String): CharSource = override fun loadAsCharSource(path: String): gay.pizza.pork.parser.CharSource =
StringCharSource(asFsPath(path).readText()) StringCharSource(asFsPath(path).readText())
override fun stableContentIdentity(path: String): String = override fun stableContentIdentity(path: String): String =

View File

@ -2,10 +2,9 @@ package gay.pizza.pork.frontend
import gay.pizza.pork.ast.CompilationUnit import gay.pizza.pork.ast.CompilationUnit
import gay.pizza.pork.ast.ImportDeclaration import gay.pizza.pork.ast.ImportDeclaration
import gay.pizza.pork.parse.DiscardNodeAttribution import gay.pizza.pork.parser.Parser
import gay.pizza.pork.parse.Parser import gay.pizza.pork.parser.TokenStreamSource
import gay.pizza.pork.parse.TokenStreamSource import gay.pizza.pork.parser.Tokenizer
import gay.pizza.pork.parse.Tokenizer
class World(val contentSource: ContentSource) { class World(val contentSource: ContentSource) {
private val units = mutableMapOf<String, CompilationUnit>() private val units = mutableMapOf<String, CompilationUnit>()
@ -19,7 +18,7 @@ class World(val contentSource: ContentSource) {
val charSource = contentSource.loadAsCharSource(path) val charSource = contentSource.loadAsCharSource(path)
val tokenizer = Tokenizer(charSource) val tokenizer = Tokenizer(charSource)
val tokenStream = tokenizer.tokenize() val tokenStream = tokenizer.tokenize()
val parser = Parser(TokenStreamSource(tokenStream), DiscardNodeAttribution) val parser = Parser(TokenStreamSource(tokenStream), gay.pizza.pork.parser.DiscardNodeAttribution)
return parser.readCompilationUnit() return parser.readCompilationUnit()
} }

9
parser/build.gradle.kts Normal file
View File

@ -0,0 +1,9 @@
plugins {
pork_module
}
dependencies {
api(project(":ast"))
implementation(project(":common"))
}

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
open class AnsiHighlightScheme : HighlightScheme { open class AnsiHighlightScheme : HighlightScheme {
override fun highlight(token: Token): Highlight { override fun highlight(token: Token): Highlight {
@ -16,11 +16,16 @@ open class AnsiHighlightScheme : HighlightScheme {
} else Highlight(token) } else Highlight(token)
} }
open fun string(): AnsiAttributes = AnsiAttributes("32m") open fun string(): AnsiAttributes =
open fun symbol(): AnsiAttributes = AnsiAttributes("33m") AnsiAttributes("32m")
open fun operator(): AnsiAttributes = AnsiAttributes("34m") open fun symbol(): AnsiAttributes =
open fun keyword(): AnsiAttributes = AnsiAttributes("35m") AnsiAttributes("33m")
open fun comment(): AnsiAttributes = AnsiAttributes("37m") open fun operator(): AnsiAttributes =
AnsiAttributes("34m")
open fun keyword(): AnsiAttributes =
AnsiAttributes("35m")
open fun comment(): AnsiAttributes =
AnsiAttributes("37m")
private fun ansi(attributes: AnsiAttributes, text: String): String = private fun ansi(attributes: AnsiAttributes, text: String): String =
"\u001b[${attributes.color}${text}\u001b[0m" "\u001b[${attributes.color}${text}\u001b[0m"

View File

@ -1,7 +1,8 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
interface CharSource : PeekableSource<Char> { interface CharSource : PeekableSource<Char> {
companion object { companion object {
@Suppress("ConstPropertyName")
const val NullChar = 0.toChar() const val NullChar = 0.toChar()
} }
} }

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
import gay.pizza.pork.ast.Node import gay.pizza.pork.ast.Node

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
class Highlight(val token: Token, val text: String? = null) { class Highlight(val token: Token, val text: String? = null) {
override fun toString(): String = text ?: token.text override fun toString(): String = text ?: token.text

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
interface HighlightScheme { interface HighlightScheme {
fun highlight(token: Token): Highlight fun highlight(token: Token): Highlight

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
class Highlighter(val scheme: HighlightScheme) { class Highlighter(val scheme: HighlightScheme) {
fun highlight(stream: TokenStream): List<Highlight> = fun highlight(stream: TokenStream): List<Highlight> =

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
import gay.pizza.pork.ast.Node import gay.pizza.pork.ast.Node

View File

@ -1,7 +1,6 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
import gay.pizza.pork.ast.* import gay.pizza.pork.ast.*
import gay.pizza.pork.util.StringEscape
class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) { class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
private val unsanitizedSource = source private val unsanitizedSource = source

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
interface PeekableSource<T> { interface PeekableSource<T> {
val currentIndex: Int val currentIndex: Int

View File

@ -1,8 +1,7 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
import gay.pizza.pork.ast.* import gay.pizza.pork.ast.*
import gay.pizza.pork.util.IndentPrinter import gay.pizza.pork.common.IndentPrinter
import gay.pizza.pork.util.StringEscape
class Printer(buffer: StringBuilder) : NodeVisitor<Unit> { class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
private val out = IndentPrinter(buffer) private val out = IndentPrinter(buffer)

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
class StringCharSource(val input: String) : CharSource { class StringCharSource(val input: String) : CharSource {
private var index = 0 private var index = 0

View File

@ -1,8 +1,7 @@
package gay.pizza.pork.util package gay.pizza.pork.parser
object StringEscape { object StringEscape {
fun escape(input: String): String = input.replace("\n", "\\n") fun escape(input: String): String = input.replace("\n", "\\n")
fun unescape(input: String): String = input.replace("\\n", "\n") fun unescape(input: String): String = input.replace("\\n", "\n")
fun unquote(input: String): String = input.substring(1, input.length - 1) fun unquote(input: String): String = input.substring(1, input.length - 1)
} }

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
class Token(val type: TokenType, val start: Int, val text: String) { class Token(val type: TokenType, val start: Int, val text: String) {
override fun toString(): String = "$start ${type.name} '${text.replace("\n", "\\n")}'" override fun toString(): String = "$start ${type.name} '${text.replace("\n", "\\n")}'"

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
enum class TokenFamily : TokenTypeProperty { enum class TokenFamily : TokenTypeProperty {
OperatorFamily, OperatorFamily,

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
import gay.pizza.pork.ast.NodeCoalescer import gay.pizza.pork.ast.NodeCoalescer
import gay.pizza.pork.ast.Node import gay.pizza.pork.ast.Node

View File

@ -1,3 +1,3 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
interface TokenSource : PeekableSource<Token> interface TokenSource : PeekableSource<Token>

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
class TokenStream(val tokens: List<Token>) { class TokenStream(val tokens: List<Token>) {
override fun toString(): String = tokens.toString() override fun toString(): String = tokens.toString()

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
class TokenStreamSource(val stream: TokenStream) : TokenSource { class TokenStreamSource(val stream: TokenStream) : TokenSource {
private var index = 0 private var index = 0

View File

@ -1,7 +1,7 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
import gay.pizza.pork.parse.TokenTypeProperty.* import gay.pizza.pork.parser.TokenTypeProperty.*
import gay.pizza.pork.parse.TokenFamily.* import gay.pizza.pork.parser.TokenFamily.*
enum class TokenType(vararg properties: TokenTypeProperty) { enum class TokenType(vararg properties: TokenTypeProperty) {
Symbol(SymbolFamily, CharConsumer { (it in 'a'..'z') || (it in 'A'..'Z') || it == '_' }, KeywordUpgrader), Symbol(SymbolFamily, CharConsumer { (it in 'a'..'z') || (it in 'A'..'Z') || it == '_' }, KeywordUpgrader),

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
interface TokenTypeProperty { interface TokenTypeProperty {
class SingleChar(val char: Char) : TokenTypeProperty class SingleChar(val char: Char) : TokenTypeProperty

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.parse package gay.pizza.pork.parser
class Tokenizer(val source: CharSource) { class Tokenizer(val source: CharSource) {
private var tokenStart: Int = 0 private var tokenStart: Int = 0

View File

@ -1,8 +1,12 @@
rootProject.name = "pork" rootProject.name = "pork"
include( include(
":common",
":ast", ":ast",
":core" ":parser",
":frontend",
":evaluator",
":tool"
) )
dependencyResolutionManagement { dependencyResolutionManagement {

View File

@ -7,18 +7,22 @@ plugins {
dependencies { dependencies {
api(project(":ast")) api(project(":ast"))
api(project(":parser"))
api(project(":frontend"))
api(project(":evaluator"))
implementation(libs.clikt) implementation(libs.clikt)
implementation(project(":common"))
} }
application { application {
mainClass.set("gay.pizza.pork.cli.MainKt") mainClass.set("gay.pizza.pork.tool.MainKt")
} }
graalvmNative { graalvmNative {
binaries { binaries {
named("main") { named("main") {
imageName.set("pork") imageName.set("pork")
mainClass.set("gay.pizza.pork.cli.MainKt") mainClass.set("gay.pizza.pork.tool.MainKt")
sharedLibrary.set(false) sharedLibrary.set(false)
} }
} }

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.cli package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.argument

View File

@ -1,10 +1,10 @@
package gay.pizza.pork.cli package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.types.path import com.github.ajalt.clikt.parameters.types.path
import gay.pizza.pork.ast.NodeCoalescer import gay.pizza.pork.ast.NodeCoalescer
import gay.pizza.pork.parse.TokenNodeAttribution import gay.pizza.pork.parser.TokenNodeAttribution
class AttributeCommand : CliktCommand(help = "Attribute AST", name = "attribute") { class AttributeCommand : CliktCommand(help = "Attribute AST", name = "attribute") {
val path by argument("file").path(mustExist = true, canBeDir = false) val path by argument("file").path(mustExist = true, canBeDir = false)

View File

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

View File

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

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.cli package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.argument

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.cli package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.core.subcommands

View File

@ -1,10 +1,10 @@
package gay.pizza.pork.cli package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.types.path import com.github.ajalt.clikt.parameters.types.path
import gay.pizza.pork.eval.CallableFunction import gay.pizza.pork.evaluator.CallableFunction
import gay.pizza.pork.eval.Scope import gay.pizza.pork.evaluator.Scope
class RunCommand : CliktCommand(help = "Run Program", name = "run") { class RunCommand : CliktCommand(help = "Run Program", name = "run") {
val path by argument("file").path(mustExist = true, canBeDir = false) val path by argument("file").path(mustExist = true, canBeDir = false)

View File

@ -1,4 +1,4 @@
package gay.pizza.pork.cli package gay.pizza.pork.tool
import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.argument

View File

@ -1,12 +1,14 @@
package gay.pizza.pork.cli package gay.pizza.pork.tool
import gay.pizza.pork.ast.NodeVisitor import gay.pizza.pork.ast.NodeVisitor
import gay.pizza.pork.parse.Printer import gay.pizza.pork.parser.Printer
import gay.pizza.pork.ast.CompilationUnit import gay.pizza.pork.ast.CompilationUnit
import gay.pizza.pork.eval.* 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.ContentSource
import gay.pizza.pork.frontend.World import gay.pizza.pork.frontend.World
import gay.pizza.pork.parse.* import gay.pizza.pork.parser.*
abstract class Tool { abstract class Tool {
abstract fun createCharSource(): CharSource abstract fun createCharSource(): CharSource

View File

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