mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 13:11:32 +00:00
Auto-generate the AST.
This commit is contained in:
@ -1,5 +1,4 @@
|
||||
plugins {
|
||||
pork_module
|
||||
|
||||
id("gay.pizza.pork.module")
|
||||
id("gay.pizza.pork.ast")
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ types:
|
||||
- name: declarations
|
||||
type: List<Declaration>
|
||||
- name: definitions
|
||||
type: List<Declaration>
|
||||
type: List<Definition>
|
||||
LetAssignment:
|
||||
parent: Expression
|
||||
values:
|
||||
|
@ -9,15 +9,16 @@ class CompilationUnit(val declarations: List<Declaration>, val definitions: List
|
||||
override val type: NodeType = NodeType.CompilationUnit
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitAll(declarations)
|
||||
visitor.visitAll(declarations, definitions)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is CompilationUnit) return false
|
||||
return other.declarations == declarations
|
||||
return other.declarations == declarations && other.definitions == definitions
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = declarations.hashCode()
|
||||
result = 31 * result + definitions.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("declaration")
|
||||
sealed class Declaration : Node()
|
||||
|
@ -1,8 +1,10 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("definition")
|
||||
sealed class Definition : Node() {
|
||||
abstract val symbol: Symbol
|
||||
abstract val modifiers: DefinitionModifiers
|
||||
|
@ -1,8 +1,8 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
class DefinitionModifiers(
|
||||
var export: Boolean
|
||||
)
|
||||
@SerialName("definitionModifiers")
|
||||
class DefinitionModifiers(var export: Boolean)
|
||||
|
@ -1,6 +1,8 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("expression")
|
||||
sealed class Expression : Node()
|
||||
|
@ -5,24 +5,20 @@ import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("functionDefinition")
|
||||
class FunctionDefinition(
|
||||
override val modifiers: DefinitionModifiers,
|
||||
override val symbol: Symbol,
|
||||
val arguments: List<Symbol>,
|
||||
val block: Block
|
||||
) : Definition() {
|
||||
class FunctionDefinition(override val modifiers: DefinitionModifiers, override val symbol: Symbol, val arguments: List<Symbol>, val block: Block) : Definition() {
|
||||
override val type: NodeType = NodeType.FunctionDefinition
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitNodes(symbol)
|
||||
visitor.visitAll(listOf(symbol), arguments, listOf(block))
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is FunctionDefinition) return false
|
||||
return other.symbol == symbol && other.arguments == arguments && other.block == block
|
||||
return other.modifiers == modifiers && other.symbol == symbol && other.arguments == arguments && other.block == block
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = symbol.hashCode()
|
||||
var result = modifiers.hashCode()
|
||||
result = 31 * result + symbol.hashCode()
|
||||
result = 31 * result + arguments.hashCode()
|
||||
result = 31 * result + block.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
|
@ -5,11 +5,7 @@ import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("if")
|
||||
class If(
|
||||
val condition: Expression,
|
||||
val thenExpression: Expression,
|
||||
val elseExpression: Expression? = null
|
||||
) : Expression() {
|
||||
class If(val condition: Expression, val thenExpression: Expression, val elseExpression: Expression?) : Expression() {
|
||||
override val type: NodeType = NodeType.If
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
@ -17,15 +13,13 @@ class If(
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is If) return false
|
||||
return other.condition == condition &&
|
||||
other.thenExpression == thenExpression &&
|
||||
other.elseExpression == elseExpression
|
||||
return other.condition == condition && other.thenExpression == thenExpression && other.elseExpression == elseExpression
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = condition.hashCode()
|
||||
result = 31 * result + thenExpression.hashCode()
|
||||
result = 31 * result + (elseExpression?.hashCode() ?: 0)
|
||||
result = 31 * result + elseExpression.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
|
@ -5,11 +5,7 @@ import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("infixOperation")
|
||||
class InfixOperation(
|
||||
val left: Expression,
|
||||
val op: InfixOperator,
|
||||
val right: Expression
|
||||
) : Expression() {
|
||||
class InfixOperation(val left: Expression, val op: InfixOperator, val right: Expression) : Expression() {
|
||||
override val type: NodeType = NodeType.InfixOperation
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
@ -17,9 +13,7 @@ class InfixOperation(
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is InfixOperation) return false
|
||||
return other.op == op &&
|
||||
other.left == left &&
|
||||
other.right == right
|
||||
return other.left == left && other.op == op && other.right == right
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
|
@ -14,7 +14,7 @@ class IntLiteral(val value: Int) : Expression() {
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = value
|
||||
var result = value.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("node")
|
||||
sealed class Node {
|
||||
abstract val type: NodeType
|
||||
open fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> = emptyList()
|
||||
|
||||
open fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
emptyList()
|
||||
}
|
||||
|
@ -1,26 +1,58 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor<Unit> {
|
||||
override fun visitIntLiteral(node: IntLiteral): Unit = handle(node)
|
||||
override fun visitStringLiteral(node: StringLiteral): Unit = handle(node)
|
||||
override fun visitBooleanLiteral(node: BooleanLiteral): Unit = handle(node)
|
||||
override fun visitListLiteral(node: ListLiteral): Unit = handle(node)
|
||||
override fun visitSymbol(node: Symbol): Unit = handle(node)
|
||||
override fun visitFunctionCall(node: FunctionCall): Unit = handle(node)
|
||||
override fun visitLetAssignment(node: LetAssignment): Unit = handle(node)
|
||||
override fun visitSymbolReference(node: SymbolReference): Unit = handle(node)
|
||||
override fun visitLambda(node: Lambda): Unit = handle(node)
|
||||
override fun visitParentheses(node: Parentheses): Unit = handle(node)
|
||||
override fun visitPrefixOperation(node: PrefixOperation): Unit = handle(node)
|
||||
override fun visitIf(node: If): Unit = handle(node)
|
||||
override fun visitInfixOperation(node: InfixOperation): Unit = handle(node)
|
||||
override fun visitFunctionDeclaration(node: FunctionDefinition): Unit = handle(node)
|
||||
override fun visitBlock(node: Block): Unit = handle(node)
|
||||
override fun visitImportDeclaration(node: ImportDeclaration): Unit = handle(node)
|
||||
override fun visitBlock(node: Block): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitCompilationUnit(node: CompilationUnit): Unit = handle(node)
|
||||
override fun visitBooleanLiteral(node: BooleanLiteral): Unit =
|
||||
handle(node)
|
||||
|
||||
private fun handle(node: Node) {
|
||||
override fun visitCompilationUnit(node: CompilationUnit): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitFunctionCall(node: FunctionCall): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitFunctionDefinition(node: FunctionDefinition): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitIf(node: If): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitImportDeclaration(node: ImportDeclaration): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitInfixOperation(node: InfixOperation): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitIntLiteral(node: IntLiteral): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitLambda(node: Lambda): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitLetAssignment(node: LetAssignment): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitListLiteral(node: ListLiteral): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitParentheses(node: Parentheses): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitPrefixOperation(node: PrefixOperation): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitStringLiteral(node: StringLiteral): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitSymbol(node: Symbol): Unit =
|
||||
handle(node)
|
||||
|
||||
override fun visitSymbolReference(node: SymbolReference): Unit =
|
||||
handle(node)
|
||||
|
||||
fun handle(node: Node) {
|
||||
handler(node)
|
||||
node.visitChildren(this)
|
||||
}
|
||||
|
@ -2,24 +2,24 @@ package gay.pizza.pork.ast
|
||||
|
||||
enum class NodeType(val parent: NodeType? = null) {
|
||||
Node,
|
||||
Symbol(Node),
|
||||
Block(Node),
|
||||
Expression(Node),
|
||||
BooleanLiteral(Expression),
|
||||
CompilationUnit(Node),
|
||||
Declaration(Node),
|
||||
Definition(Node),
|
||||
Block(Node),
|
||||
CompilationUnit(Node),
|
||||
IntLiteral(Expression),
|
||||
BooleanLiteral(Expression),
|
||||
ListLiteral(Expression),
|
||||
StringLiteral(Expression),
|
||||
Parentheses(Expression),
|
||||
LetAssignment(Expression),
|
||||
Lambda(Expression),
|
||||
PrefixOperation(Expression),
|
||||
InfixOperation(Expression),
|
||||
SymbolReference(Expression),
|
||||
FunctionCall(Expression),
|
||||
FunctionDefinition(Definition),
|
||||
If(Expression),
|
||||
ImportDeclaration(Declaration),
|
||||
FunctionDefinition(Definition)
|
||||
InfixOperation(Expression),
|
||||
IntLiteral(Expression),
|
||||
Lambda(Expression),
|
||||
LetAssignment(Expression),
|
||||
ListLiteral(Expression),
|
||||
Parentheses(Expression),
|
||||
PrefixOperation(Expression),
|
||||
StringLiteral(Expression),
|
||||
Symbol(Node),
|
||||
SymbolReference(Expression)
|
||||
}
|
||||
|
@ -1,60 +1,64 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
interface NodeVisitor<T> {
|
||||
fun visitIntLiteral(node: IntLiteral): T
|
||||
fun visitStringLiteral(node: StringLiteral): T
|
||||
fun visitBooleanLiteral(node: BooleanLiteral): T
|
||||
fun visitListLiteral(node: ListLiteral): T
|
||||
fun visitSymbol(node: Symbol): T
|
||||
fun visitFunctionCall(node: FunctionCall): T
|
||||
fun visitLetAssignment(node: LetAssignment): 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 visitFunctionDeclaration(node: FunctionDefinition): T
|
||||
fun visitBlock(node: Block): T
|
||||
|
||||
fun visitImportDeclaration(node: ImportDeclaration): T
|
||||
fun visitBooleanLiteral(node: BooleanLiteral): T
|
||||
|
||||
fun visitCompilationUnit(node: CompilationUnit): 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 FunctionCall -> visitFunctionCall(node)
|
||||
is LetAssignment -> visitLetAssignment(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 visitFunctionCall(node: FunctionCall): T
|
||||
|
||||
fun visitDeclaration(node: Declaration): T = when (node) {
|
||||
is ImportDeclaration -> visitImportDeclaration(node)
|
||||
}
|
||||
fun visitFunctionDefinition(node: FunctionDefinition): T
|
||||
|
||||
fun visitDefinition(node: Definition): T = when (node) {
|
||||
is FunctionDefinition -> visitFunctionDeclaration(node)
|
||||
}
|
||||
fun visitIf(node: If): T
|
||||
|
||||
fun visit(node: Node): T = when (node) {
|
||||
is Symbol -> visitSymbol(node)
|
||||
is Expression -> visitExpression(node)
|
||||
is CompilationUnit -> visitCompilationUnit(node)
|
||||
is Block -> visitBlock(node)
|
||||
is Declaration -> visitDeclaration(node)
|
||||
is Definition -> visitDefinition(node)
|
||||
}
|
||||
fun visitImportDeclaration(node: ImportDeclaration): T
|
||||
|
||||
fun visitInfixOperation(node: InfixOperation): T
|
||||
|
||||
fun visitIntLiteral(node: IntLiteral): T
|
||||
|
||||
fun visitLambda(node: Lambda): T
|
||||
|
||||
fun visitLetAssignment(node: LetAssignment): T
|
||||
|
||||
fun visitListLiteral(node: ListLiteral): T
|
||||
|
||||
fun visitParentheses(node: Parentheses): T
|
||||
|
||||
fun visitPrefixOperation(node: PrefixOperation): T
|
||||
|
||||
fun visitStringLiteral(node: StringLiteral): T
|
||||
|
||||
fun visitSymbol(node: Symbol): T
|
||||
|
||||
fun visitSymbolReference(node: SymbolReference): T
|
||||
|
||||
fun visitNodes(vararg nodes: Node?): List<T> =
|
||||
nodes.asSequence().filterNotNull().map { visit(it) }.toList()
|
||||
|
||||
fun visitAll(vararg nodeLists: List<Node>): List<T> =
|
||||
nodeLists.asSequence().flatten().map { visit(it) }.toList()
|
||||
|
||||
fun visit(node: Node): T =
|
||||
when (node) {
|
||||
is Symbol -> visitSymbol(node)
|
||||
is Block -> visitBlock(node)
|
||||
is CompilationUnit -> visitCompilationUnit(node)
|
||||
is LetAssignment -> visitLetAssignment(node)
|
||||
is InfixOperation -> visitInfixOperation(node)
|
||||
is BooleanLiteral -> visitBooleanLiteral(node)
|
||||
is FunctionCall -> visitFunctionCall(node)
|
||||
is FunctionDefinition -> visitFunctionDefinition(node)
|
||||
is If -> visitIf(node)
|
||||
is ImportDeclaration -> visitImportDeclaration(node)
|
||||
is IntLiteral -> visitIntLiteral(node)
|
||||
is Lambda -> visitLambda(node)
|
||||
is ListLiteral -> visitListLiteral(node)
|
||||
is Parentheses -> visitParentheses(node)
|
||||
is PrefixOperation -> visitPrefixOperation(node)
|
||||
is StringLiteral -> visitStringLiteral(node)
|
||||
is SymbolReference -> visitSymbolReference(node)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user