mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-02 12:50:55 +00:00
Define node visitor order based on parsing order.
This commit is contained in:
parent
900e3f1a1c
commit
941b201549
@ -3,11 +3,11 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
plugins {
|
||||
application
|
||||
|
||||
kotlin("jvm") version "1.9.0"
|
||||
kotlin("plugin.serialization") version "1.9.0"
|
||||
kotlin("jvm") version "1.9.10"
|
||||
kotlin("plugin.serialization") version "1.9.10"
|
||||
|
||||
id("com.github.johnrengelman.shadow") version "8.1.1"
|
||||
id("org.graalvm.buildtools.native") version "0.9.23"
|
||||
id("org.graalvm.buildtools.native") version "0.9.25"
|
||||
}
|
||||
|
||||
repositories {
|
||||
@ -22,9 +22,8 @@ java {
|
||||
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlin:kotlin-bom")
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||
implementation("com.github.ajalt.clikt:clikt:4.2.0")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0-RC")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
|
@ -3,18 +3,18 @@ package gay.pizza.pork.ast
|
||||
import gay.pizza.pork.ast.nodes.*
|
||||
|
||||
class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor<Unit> {
|
||||
override fun visitDefine(node: Define) = handler(node)
|
||||
override fun visitFunctionCall(node: FunctionCall) = handler(node)
|
||||
override fun visitReference(node: SymbolReference) = handler(node)
|
||||
override fun visitIf(node: If) = handler(node)
|
||||
override fun visitSymbol(node: Symbol) = handler(node)
|
||||
override fun visitLambda(node: Lambda) = handler(node)
|
||||
override fun visitIntLiteral(node: IntLiteral) = handler(node)
|
||||
override fun visitBooleanLiteral(node: BooleanLiteral) = handler(node)
|
||||
override fun visitListLiteral(node: ListLiteral) = handler(node)
|
||||
override fun visitStringLiteral(node: StringLiteral) = handler(node)
|
||||
override fun visitParentheses(node: Parentheses) = handler(node)
|
||||
override fun visitPrefixOperation(node: PrefixOperation) = handler(node)
|
||||
override fun visitInfixOperation(node: InfixOperation) = handler(node)
|
||||
override fun visitProgram(node: Program) = handler(node)
|
||||
override fun visitIntLiteral(node: IntLiteral): Unit = handler(node)
|
||||
override fun visitStringLiteral(node: StringLiteral): Unit = handler(node)
|
||||
override fun visitBooleanLiteral(node: BooleanLiteral): Unit = handler(node)
|
||||
override fun visitListLiteral(node: ListLiteral): Unit = handler(node)
|
||||
override fun visitSymbol(node: Symbol): Unit = handler(node)
|
||||
override fun visitFunctionCall(node: FunctionCall): Unit = handler(node)
|
||||
override fun visitDefine(node: Define): Unit = handler(node)
|
||||
override fun visitSymbolReference(node: SymbolReference): Unit = handler(node)
|
||||
override fun visitLambda(node: Lambda): Unit = handler(node)
|
||||
override fun visitParentheses(node: Parentheses): Unit = handler(node)
|
||||
override fun visitPrefixOperation(node: PrefixOperation): Unit = handler(node)
|
||||
override fun visitIf(node: If): Unit = handler(node)
|
||||
override fun visitInfixOperation(node: InfixOperation): Unit = handler(node)
|
||||
override fun visitProgram(node: Program): Unit = handler(node)
|
||||
}
|
||||
|
@ -3,47 +3,44 @@ package gay.pizza.pork.ast
|
||||
import gay.pizza.pork.ast.nodes.*
|
||||
|
||||
interface NodeVisitor<T> {
|
||||
fun visitDefine(node: Define): T
|
||||
fun visitFunctionCall(node: FunctionCall): T
|
||||
fun visitReference(node: SymbolReference): T
|
||||
fun visitIf(node: If): T
|
||||
fun visitSymbol(node: Symbol): T
|
||||
fun visitLambda(node: Lambda): T
|
||||
|
||||
fun visitIntLiteral(node: IntLiteral): T
|
||||
fun visitStringLiteral(node: StringLiteral): T
|
||||
fun visitBooleanLiteral(node: BooleanLiteral): T
|
||||
fun visitListLiteral(node: ListLiteral): T
|
||||
fun visitStringLiteral(node: StringLiteral): T
|
||||
|
||||
fun visitSymbol(node: Symbol): T
|
||||
fun visitFunctionCall(node: FunctionCall): T
|
||||
fun visitDefine(node: Define): T
|
||||
fun visitSymbolReference(node: SymbolReference): T
|
||||
fun visitLambda(node: Lambda): T
|
||||
fun visitParentheses(node: Parentheses): T
|
||||
fun visitPrefixOperation(node: PrefixOperation): T
|
||||
fun visitIf(node: If): T
|
||||
fun visitInfixOperation(node: InfixOperation): T
|
||||
|
||||
fun visitProgram(node: Program): T
|
||||
|
||||
fun visitExpression(node: Expression): T = when (node) {
|
||||
is IntLiteral -> visitIntLiteral(node)
|
||||
is StringLiteral -> visitStringLiteral(node)
|
||||
is BooleanLiteral -> visitBooleanLiteral(node)
|
||||
is ListLiteral -> visitListLiteral(node)
|
||||
is StringLiteral -> visitStringLiteral(node)
|
||||
is Parentheses -> visitParentheses(node)
|
||||
is InfixOperation -> visitInfixOperation(node)
|
||||
is PrefixOperation -> visitPrefixOperation(node)
|
||||
is Define -> visitDefine(node)
|
||||
is Lambda -> visitLambda(node)
|
||||
is FunctionCall -> visitFunctionCall(node)
|
||||
is SymbolReference -> visitReference(node)
|
||||
is Define -> visitDefine(node)
|
||||
is SymbolReference -> visitSymbolReference(node)
|
||||
is Lambda -> visitLambda(node)
|
||||
is Parentheses -> visitParentheses(node)
|
||||
is PrefixOperation -> visitPrefixOperation(node)
|
||||
is If -> visitIf(node)
|
||||
is InfixOperation -> visitInfixOperation(node)
|
||||
}
|
||||
|
||||
fun visit(node: Node): T = when (node) {
|
||||
is Expression -> visitExpression(node)
|
||||
is Symbol -> visitSymbol(node)
|
||||
is Expression -> visitExpression(node)
|
||||
is Program -> visitProgram(node)
|
||||
}
|
||||
|
||||
fun visitNodes(vararg nodes: Node?): List<T> =
|
||||
nodes.filterNotNull().map { visit(it) }
|
||||
nodes.asSequence().filterNotNull().map { visit(it) }.toList()
|
||||
|
||||
fun visitAll(vararg nodeLists: List<Node>): List<T> =
|
||||
nodeLists.asSequence().flatten().map { visit(it) }.toList()
|
||||
|
@ -20,10 +20,37 @@ class Printer(private val buffer: StringBuilder) : NodeVisitor<Unit> {
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitDefine(node: Define) {
|
||||
visit(node.symbol)
|
||||
append(" = ")
|
||||
visit(node.value)
|
||||
override fun visitIntLiteral(node: IntLiteral) {
|
||||
append(node.value.toString())
|
||||
}
|
||||
|
||||
override fun visitStringLiteral(node: StringLiteral) {
|
||||
append("\"")
|
||||
append(StringEscape.escape(node.text))
|
||||
append("\"")
|
||||
}
|
||||
|
||||
override fun visitBooleanLiteral(node: BooleanLiteral) {
|
||||
if (node.value) {
|
||||
append("true")
|
||||
} else {
|
||||
append("false")
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitListLiteral(node: ListLiteral) {
|
||||
append("[")
|
||||
for ((index, item) in node.items.withIndex()) {
|
||||
visit(item)
|
||||
if (index != node.items.size - 1) {
|
||||
append(", ")
|
||||
}
|
||||
}
|
||||
append("]")
|
||||
}
|
||||
|
||||
override fun visitSymbol(node: Symbol) {
|
||||
append(node.id)
|
||||
}
|
||||
|
||||
override fun visitFunctionCall(node: FunctionCall) {
|
||||
@ -38,24 +65,16 @@ class Printer(private val buffer: StringBuilder) : NodeVisitor<Unit> {
|
||||
append(")")
|
||||
}
|
||||
|
||||
override fun visitReference(node: SymbolReference) {
|
||||
override fun visitDefine(node: Define) {
|
||||
visit(node.symbol)
|
||||
append(" = ")
|
||||
visit(node.value)
|
||||
}
|
||||
|
||||
override fun visitSymbolReference(node: SymbolReference) {
|
||||
visit(node.symbol)
|
||||
}
|
||||
|
||||
override fun visitIf(node: If) {
|
||||
append("if ")
|
||||
visit(node.condition)
|
||||
append(" then ")
|
||||
visit(node.thenExpression)
|
||||
if (node.elseExpression != null) {
|
||||
append(" else ")
|
||||
visit(node.elseExpression)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitSymbol(node: Symbol) {
|
||||
append(node.id)
|
||||
}
|
||||
|
||||
override fun visitLambda(node: Lambda) {
|
||||
append("{")
|
||||
@ -87,35 +106,6 @@ class Printer(private val buffer: StringBuilder) : NodeVisitor<Unit> {
|
||||
append("}")
|
||||
}
|
||||
|
||||
override fun visitIntLiteral(node: IntLiteral) {
|
||||
append(node.value.toString())
|
||||
}
|
||||
|
||||
override fun visitBooleanLiteral(node: BooleanLiteral) {
|
||||
if (node.value) {
|
||||
append("true")
|
||||
} else {
|
||||
append("false")
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitListLiteral(node: ListLiteral) {
|
||||
append("[")
|
||||
for ((index, item) in node.items.withIndex()) {
|
||||
visit(item)
|
||||
if (index != node.items.size - 1) {
|
||||
append(", ")
|
||||
}
|
||||
}
|
||||
append("]")
|
||||
}
|
||||
|
||||
override fun visitStringLiteral(node: StringLiteral) {
|
||||
append("\"")
|
||||
append(StringEscape.escape(node.text))
|
||||
append("\"")
|
||||
}
|
||||
|
||||
override fun visitParentheses(node: Parentheses) {
|
||||
append("(")
|
||||
visit(node.expression)
|
||||
@ -127,6 +117,17 @@ class Printer(private val buffer: StringBuilder) : NodeVisitor<Unit> {
|
||||
visit(node.expression)
|
||||
}
|
||||
|
||||
override fun visitIf(node: If) {
|
||||
append("if ")
|
||||
visit(node.condition)
|
||||
append(" then ")
|
||||
visit(node.thenExpression)
|
||||
if (node.elseExpression != null) {
|
||||
append(" else ")
|
||||
visit(node.elseExpression)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitInfixOperation(node: InfixOperation) {
|
||||
visit(node.left)
|
||||
append(" ")
|
||||
|
@ -5,49 +5,12 @@ import gay.pizza.pork.ast.nodes.*
|
||||
import gay.pizza.pork.util.StringEscape
|
||||
|
||||
class DartCompiler : NodeVisitor<String> {
|
||||
override fun visitDefine(node: Define): String =
|
||||
"final ${visit(node.symbol)} = ${visit(node.value)};"
|
||||
|
||||
override fun visitFunctionCall(node: FunctionCall): String =
|
||||
"${visit(node.symbol)}(${node.arguments.joinToString(", ") { visit(it) }})"
|
||||
|
||||
override fun visitReference(node: SymbolReference): String =
|
||||
visit(node.symbol)
|
||||
|
||||
override fun visitIf(node: If): String = buildString {
|
||||
append("if (")
|
||||
append(visit(node.condition))
|
||||
append(") {")
|
||||
append(visit(node.thenExpression))
|
||||
append("}")
|
||||
if (node.elseExpression != null) {
|
||||
append(" else {")
|
||||
append(visit(node.elseExpression))
|
||||
append("}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitSymbol(node: Symbol): String =
|
||||
node.id
|
||||
|
||||
override fun visitLambda(node: Lambda): String = buildString {
|
||||
append("(${node.arguments.joinToString(", ") { visit(it) }}) {")
|
||||
appendLine()
|
||||
for ((index, expression) in node.expressions.withIndex()) {
|
||||
val code = visit(expression)
|
||||
if (index == node.expressions.size - 1) {
|
||||
append("return ");
|
||||
}
|
||||
append(code)
|
||||
append(";")
|
||||
}
|
||||
appendLine()
|
||||
append("}")
|
||||
}
|
||||
|
||||
override fun visitIntLiteral(node: IntLiteral): String =
|
||||
node.value.toString()
|
||||
|
||||
override fun visitStringLiteral(node: StringLiteral): String =
|
||||
"\"" + StringEscape.escape(node.text) + "\""
|
||||
|
||||
override fun visitBooleanLiteral(node: BooleanLiteral): String =
|
||||
node.value.toString()
|
||||
|
||||
@ -63,8 +26,32 @@ class DartCompiler : NodeVisitor<String> {
|
||||
append("]")
|
||||
}
|
||||
|
||||
override fun visitStringLiteral(node: StringLiteral): String =
|
||||
"\"" + StringEscape.escape(node.text) + "\""
|
||||
override fun visitSymbol(node: Symbol): String =
|
||||
node.id
|
||||
|
||||
override fun visitFunctionCall(node: FunctionCall): String =
|
||||
"${visit(node.symbol)}(${node.arguments.joinToString(", ") { visit(it) }})"
|
||||
|
||||
override fun visitDefine(node: Define): String =
|
||||
"final ${visit(node.symbol)} = ${visit(node.value)};"
|
||||
|
||||
override fun visitSymbolReference(node: SymbolReference): String =
|
||||
visit(node.symbol)
|
||||
|
||||
override fun visitLambda(node: Lambda): String = buildString {
|
||||
append("(${node.arguments.joinToString(", ") { visit(it) }}) {")
|
||||
appendLine()
|
||||
for ((index, expression) in node.expressions.withIndex()) {
|
||||
val code = visit(expression)
|
||||
if (index == node.expressions.size - 1) {
|
||||
append("return ");
|
||||
}
|
||||
append(code)
|
||||
append(";")
|
||||
}
|
||||
appendLine()
|
||||
append("}")
|
||||
}
|
||||
|
||||
override fun visitParentheses(node: Parentheses): String =
|
||||
"(${visit(node.expression)})"
|
||||
@ -72,6 +59,19 @@ class DartCompiler : NodeVisitor<String> {
|
||||
override fun visitPrefixOperation(node: PrefixOperation): String =
|
||||
"${node.op.token}${visit(node.expression)}"
|
||||
|
||||
override fun visitIf(node: If): String = buildString {
|
||||
append("if (")
|
||||
append(visit(node.condition))
|
||||
append(") {")
|
||||
append(visit(node.thenExpression))
|
||||
append("}")
|
||||
if (node.elseExpression != null) {
|
||||
append(" else {")
|
||||
append(visit(node.elseExpression))
|
||||
append("}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitInfixOperation(node: InfixOperation): String =
|
||||
"${visit(node.left)} ${node.op.token} ${visit(node.right)}"
|
||||
|
||||
|
@ -5,42 +5,12 @@ import gay.pizza.pork.ast.nodes.*
|
||||
import gay.pizza.pork.util.StringEscape
|
||||
|
||||
class KotlinCompiler : NodeVisitor<String> {
|
||||
override fun visitDefine(node: Define): String =
|
||||
"val ${visit(node.symbol)} = ${visit(node.value)}"
|
||||
|
||||
override fun visitFunctionCall(node: FunctionCall): String =
|
||||
"${visit(node.symbol)}(${node.arguments.joinToString(", ") { visit(it) }})"
|
||||
|
||||
override fun visitReference(node: SymbolReference): String =
|
||||
visit(node.symbol)
|
||||
|
||||
override fun visitIf(node: If): String = buildString {
|
||||
append("if (")
|
||||
append(visit(node.condition))
|
||||
append(") {")
|
||||
append(visit(node.thenExpression))
|
||||
append("}")
|
||||
if (node.elseExpression != null) {
|
||||
append(" else {")
|
||||
append(visit(node.elseExpression))
|
||||
append("}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitSymbol(node: Symbol): String =
|
||||
node.id
|
||||
|
||||
override fun visitLambda(node: Lambda): String = buildString {
|
||||
append("{ ${node.arguments.joinToString(", ") { visit(it) }} ->")
|
||||
appendLine()
|
||||
append(visitAll(node.expressions).joinToString("\n"))
|
||||
appendLine()
|
||||
append("}")
|
||||
}
|
||||
|
||||
override fun visitIntLiteral(node: IntLiteral): String =
|
||||
node.value.toString()
|
||||
|
||||
override fun visitStringLiteral(node: StringLiteral): String =
|
||||
"\"" + StringEscape.escape(node.text) + "\""
|
||||
|
||||
override fun visitBooleanLiteral(node: BooleanLiteral): String =
|
||||
node.value.toString()
|
||||
|
||||
@ -56,8 +26,25 @@ class KotlinCompiler : NodeVisitor<String> {
|
||||
append(")")
|
||||
}
|
||||
|
||||
override fun visitStringLiteral(node: StringLiteral): String =
|
||||
"\"" + StringEscape.escape(node.text) + "\""
|
||||
override fun visitSymbol(node: Symbol): String =
|
||||
node.id
|
||||
|
||||
override fun visitFunctionCall(node: FunctionCall): String =
|
||||
"${visit(node.symbol)}(${node.arguments.joinToString(", ") { visit(it) }})"
|
||||
|
||||
override fun visitDefine(node: Define): String =
|
||||
"val ${visit(node.symbol)} = ${visit(node.value)}"
|
||||
|
||||
override fun visitSymbolReference(node: SymbolReference): String =
|
||||
visit(node.symbol)
|
||||
|
||||
override fun visitLambda(node: Lambda): String = buildString {
|
||||
append("{ ${node.arguments.joinToString(", ") { visit(it) }} ->")
|
||||
appendLine()
|
||||
append(visitAll(node.expressions).joinToString("\n"))
|
||||
appendLine()
|
||||
append("}")
|
||||
}
|
||||
|
||||
override fun visitParentheses(node: Parentheses): String =
|
||||
"(${visit(node.expression)})"
|
||||
@ -65,6 +52,19 @@ class KotlinCompiler : NodeVisitor<String> {
|
||||
override fun visitPrefixOperation(node: PrefixOperation): String =
|
||||
"${node.op.token}${visit(node.expression)}"
|
||||
|
||||
override fun visitIf(node: If): String = buildString {
|
||||
append("if (")
|
||||
append(visit(node.condition))
|
||||
append(") {")
|
||||
append(visit(node.thenExpression))
|
||||
append("}")
|
||||
if (node.elseExpression != null) {
|
||||
append(" else {")
|
||||
append(visit(node.elseExpression))
|
||||
append("}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitInfixOperation(node: InfixOperation): String =
|
||||
"${visit(node.left)} ${node.op.token} ${visit(node.right)}"
|
||||
|
||||
|
@ -6,37 +6,27 @@ import gay.pizza.pork.ast.nodes.*
|
||||
class Evaluator(root: Scope) : NodeVisitor<Any> {
|
||||
private var currentScope: Scope = root
|
||||
|
||||
override fun visitDefine(node: Define): Any {
|
||||
val value = visit(node.value)
|
||||
currentScope.define(node.symbol.id, value)
|
||||
return value
|
||||
}
|
||||
override fun visitIntLiteral(node: IntLiteral): Any = node.value
|
||||
override fun visitStringLiteral(node: StringLiteral): Any = node.text
|
||||
override fun visitBooleanLiteral(node: BooleanLiteral): Any = node.value
|
||||
override fun visitListLiteral(node: ListLiteral): Any = node.items.map { visit(it) }
|
||||
|
||||
override fun visitSymbol(node: Symbol): Any = None
|
||||
|
||||
override fun visitFunctionCall(node: FunctionCall): Any {
|
||||
val arguments = node.arguments.map { visit(it) }
|
||||
return currentScope.call(node.symbol.id, Arguments(arguments))
|
||||
}
|
||||
|
||||
override fun visitReference(node: SymbolReference): Any =
|
||||
override fun visitDefine(node: Define): Any {
|
||||
val value = visit(node.value)
|
||||
currentScope.define(node.symbol.id, value)
|
||||
return value
|
||||
}
|
||||
|
||||
override fun visitSymbolReference(node: SymbolReference): Any =
|
||||
currentScope.value(node.symbol.id)
|
||||
|
||||
override fun visitIf(node: If): Any {
|
||||
val condition = visit(node.condition)
|
||||
return if (condition == true) {
|
||||
visit(node.thenExpression)
|
||||
} else {
|
||||
if (node.elseExpression != null) {
|
||||
visit(node.elseExpression)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitSymbol(node: Symbol): Any {
|
||||
return None
|
||||
}
|
||||
|
||||
override fun visitLambda(node: Lambda): CallableFunction {
|
||||
return CallableFunction { arguments ->
|
||||
currentScope = currentScope.fork()
|
||||
@ -55,11 +45,6 @@ class Evaluator(root: Scope) : NodeVisitor<Any> {
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitIntLiteral(node: IntLiteral): Any = node.value
|
||||
override fun visitBooleanLiteral(node: BooleanLiteral): Any = node.value
|
||||
override fun visitListLiteral(node: ListLiteral): Any = node.items.map { visit(it) }
|
||||
override fun visitStringLiteral(node: StringLiteral): Any = node.text
|
||||
|
||||
override fun visitParentheses(node: Parentheses): Any = visit(node.expression)
|
||||
|
||||
override fun visitPrefixOperation(node: PrefixOperation): Any {
|
||||
@ -74,6 +59,19 @@ class Evaluator(root: Scope) : NodeVisitor<Any> {
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitIf(node: If): Any {
|
||||
val condition = visit(node.condition)
|
||||
return if (condition == true) {
|
||||
visit(node.thenExpression)
|
||||
} else {
|
||||
if (node.elseExpression != null) {
|
||||
visit(node.elseExpression)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitInfixOperation(node: InfixOperation): Any {
|
||||
val left = visit(node.left)
|
||||
val right = visit(node.right)
|
||||
|
@ -77,7 +77,7 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
||||
Parentheses(expression)
|
||||
}
|
||||
|
||||
private fun readNegation(): PrefixOperation = within {
|
||||
private fun readPrefixOperation(): PrefixOperation = within {
|
||||
expect(TokenType.Negation) {
|
||||
PrefixOperation(PrefixOperator.Negate, readExpression())
|
||||
}
|
||||
@ -127,7 +127,7 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
||||
}
|
||||
|
||||
TokenType.Negation -> {
|
||||
readNegation()
|
||||
readPrefixOperation()
|
||||
}
|
||||
|
||||
TokenType.If -> {
|
||||
|
Loading…
Reference in New Issue
Block a user