ast: utilize extension functions to prevent larger stack frames from default interface methods

This commit is contained in:
2023-09-05 14:04:39 -07:00
parent 290d8d0f0a
commit 9f90e05d8a
53 changed files with 491 additions and 282 deletions

View File

@ -2,14 +2,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
import gay.pizza.dough.fs.PlatformFsProvider
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)
val path by argument("file")
private val json = Json {
prettyPrint = true
@ -18,7 +18,7 @@ class AstCommand : CliktCommand(help = "Print AST", name = "ast") {
}
override fun run() {
val tool = FileTool(path)
val tool = FileTool(PlatformFsProvider.resolve(path))
println(json.encodeToString(Node.serializer(), tool.parse()))
}
}

View File

@ -2,15 +2,16 @@ 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.dough.fs.PlatformFsProvider
import gay.pizza.pork.ast.NodeCoalescer
import gay.pizza.pork.ast.visit
import gay.pizza.pork.parser.TokenNodeAttribution
class AttributeCommand : CliktCommand(help = "Attribute AST", name = "attribute") {
val path by argument("file").path(mustExist = true, canBeDir = false)
val path by argument("file")
override fun run() {
val tool = FileTool(path)
val tool = FileTool(PlatformFsProvider.resolve(path))
val attribution = TokenNodeAttribution()
val compilationUnit = tool.parse(attribution)

View File

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

View File

@ -2,14 +2,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
import gay.pizza.dough.fs.PlatformFsProvider
import gay.pizza.pork.parser.AnsiHighlightScheme
class HighlightCommand : CliktCommand(help = "Syntax Highlighter", name = "highlight") {
val path by argument("file").path(mustExist = true, canBeDir = false)
val path by argument("file")
override fun run() {
val tool = FileTool(path)
val tool = FileTool(PlatformFsProvider.resolve(path))
print(tool.highlight(AnsiHighlightScheme()).joinToString(""))
}
}

View File

@ -0,0 +1,23 @@
package gay.pizza.pork.tool
import kotlin.system.measureNanoTime
fun maybeLoopAndMeasure(loop: Boolean, measure: Boolean, block: () -> Unit) {
fun withMaybeMeasurement() {
if (measure) {
val nanos = measureNanoTime(block)
val millis = nanos / 1000000.0
System.err.println("time taken: $millis ms (${nanos} ns)")
} else {
block()
}
}
if (loop) {
while (true) {
withMaybeMeasurement()
}
} else {
withMaybeMeasurement()
}
}

View File

@ -0,0 +1,21 @@
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.options.flag
import com.github.ajalt.clikt.parameters.options.option
import gay.pizza.dough.fs.PlatformFsProvider
class ParseCommand : CliktCommand(help = "Parse Compilation Unit", name = "parse") {
val loop by option("--loop", help = "Loop Parsing").flag()
val measure by option("--measure", help = "Measure Time").flag()
val path by argument("file")
override fun run() {
val tool = FileTool(PlatformFsProvider.resolve(path))
maybeLoopAndMeasure(loop, measure) {
tool.parse()
}
}
}

View File

@ -2,13 +2,13 @@ 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.dough.fs.PlatformFsProvider
class ReprintCommand : CliktCommand(help = "Reprint Parsed Compilation Unit", name = "reprint") {
val path by argument("file").path(mustExist = true, canBeDir = false)
val path by argument("file")
override fun run() {
val tool = FileTool(path)
val tool = FileTool(PlatformFsProvider.resolve(path))
print(tool.reprint())
}
}

View File

@ -13,6 +13,7 @@ class RootCommand : CliktCommand(
HighlightCommand(),
TokenizeCommand(),
ReprintCommand(),
ParseCommand(),
AstCommand(),
AttributeCommand()
)

View File

@ -4,45 +4,32 @@ import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.options.flag
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.types.path
import gay.pizza.dough.fs.PlatformFsProvider
import gay.pizza.pork.evaluator.CallableFunction
import gay.pizza.pork.evaluator.None
import gay.pizza.pork.evaluator.Scope
import kotlin.system.measureTimeMillis
class RunCommand : CliktCommand(help = "Run Program", name = "run") {
val loop by option("--loop", help = "Loop Program").flag()
val measure by option("--measure", help = "Measure Time").flag()
val path by argument("file").path(mustExist = true, canBeDir = false)
val quiet by option("--quiet", help = "Silence Prints").flag()
val path by argument("file")
override fun run() {
if (loop) {
while (true) {
runProgramMaybeMeasure()
}
} else {
runProgramMaybeMeasure()
}
}
private fun runProgramMaybeMeasure() {
if (measure) {
val time = measureTimeMillis {
runProgramOnce()
}
println("time taken: $time ms")
} else {
runProgramOnce()
}
}
private fun runProgramOnce() {
val tool = FileTool(path)
val tool = FileTool(PlatformFsProvider.resolve(path))
val scope = Scope()
scope.define("println", CallableFunction { arguments ->
if (quiet) {
return@CallableFunction None
}
for (argument in arguments.values) {
println(argument)
}
None
})
tool.evaluate(scope)
maybeLoopAndMeasure(loop, measure) {
tool.evaluate(scope)
}
}
}

View File

@ -2,13 +2,13 @@ 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.dough.fs.PlatformFsProvider
class TokenizeCommand : CliktCommand(help = "Tokenize Compilation Unit", name = "tokenize") {
val path by argument("file").path(mustExist = true, canBeDir = false)
val path by argument("file")
override fun run() {
val tool = FileTool(path)
val tool = FileTool(PlatformFsProvider.resolve(path))
val tokenStream = tool.tokenize()
for (token in tokenStream.tokens) {
println("${token.start} ${token.type.name} '${sanitize(token.text)}'")

View File

@ -3,6 +3,7 @@ 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.ast.visit
import gay.pizza.pork.evaluator.Arguments
import gay.pizza.pork.evaluator.Evaluator
import gay.pizza.pork.evaluator.Scope