mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 13:11:32 +00:00
Multi-module arrangement and the start of AST generation.
This commit is contained in:
5
ast/build.gradle.kts
Normal file
5
ast/build.gradle.kts
Normal file
@ -0,0 +1,5 @@
|
||||
plugins {
|
||||
pork_module
|
||||
|
||||
id("gay.pizza.pork.ast")
|
||||
}
|
38
ast/src/main/ast/pork.yml
Normal file
38
ast/src/main/ast/pork.yml
Normal file
@ -0,0 +1,38 @@
|
||||
root: Node
|
||||
types:
|
||||
Expression:
|
||||
parent: Node
|
||||
Symbol:
|
||||
parent: Node
|
||||
Declaration:
|
||||
parent: Node
|
||||
Definition:
|
||||
parent: Node
|
||||
values:
|
||||
- name: symbol
|
||||
type: Symbol
|
||||
- name: modifiers
|
||||
type: DefinitionModifiers
|
||||
DefinitionModifiers:
|
||||
values:
|
||||
- name: export
|
||||
type: Boolean
|
||||
Block:
|
||||
parent: Node
|
||||
values:
|
||||
- name: expressions
|
||||
type: List<Expression>
|
||||
CompilationUnit:
|
||||
parent: Node
|
||||
values:
|
||||
- name: declarations
|
||||
type: List<Declaration>
|
||||
- name: definitions
|
||||
type: List<Declaration>
|
||||
Assignment:
|
||||
parent: Expression
|
||||
values:
|
||||
- name: symbol
|
||||
type: Symbol
|
||||
- name: value
|
||||
type: Expression
|
25
ast/src/main/kotlin/gay/pizza/pork/ast/Assignment.kt
Normal file
25
ast/src/main/kotlin/gay/pizza/pork/ast/Assignment.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("assignment")
|
||||
class Assignment(val symbol: Symbol, val value: Expression) : Expression() {
|
||||
override val type: NodeType = NodeType.Assignment
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitNodes(symbol, value)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is Assignment) return false
|
||||
return other.symbol == symbol && other.value == value
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = symbol.hashCode()
|
||||
result = 31 * result + value.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
24
ast/src/main/kotlin/gay/pizza/pork/ast/Block.kt
Normal file
24
ast/src/main/kotlin/gay/pizza/pork/ast/Block.kt
Normal file
@ -0,0 +1,24 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("block")
|
||||
class Block(val expressions: List<Expression>) : Node() {
|
||||
override val type: NodeType = NodeType.Block
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitAll(expressions)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is Block) return false
|
||||
return other.expressions == expressions
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = expressions.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
21
ast/src/main/kotlin/gay/pizza/pork/ast/BooleanLiteral.kt
Normal file
21
ast/src/main/kotlin/gay/pizza/pork/ast/BooleanLiteral.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("booleanLiteral")
|
||||
class BooleanLiteral(val value: Boolean) : Expression() {
|
||||
override val type: NodeType = NodeType.BooleanLiteral
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is BooleanLiteral) return false
|
||||
return other.value == value
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = value.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
24
ast/src/main/kotlin/gay/pizza/pork/ast/CompilationUnit.kt
Normal file
24
ast/src/main/kotlin/gay/pizza/pork/ast/CompilationUnit.kt
Normal file
@ -0,0 +1,24 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("compilationUnit")
|
||||
class CompilationUnit(val declarations: List<Declaration>, val definitions: List<Definition>) : Node() {
|
||||
override val type: NodeType = NodeType.CompilationUnit
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitAll(declarations)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is CompilationUnit) return false
|
||||
return other.declarations == declarations
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = declarations.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
6
ast/src/main/kotlin/gay/pizza/pork/ast/Declaration.kt
Normal file
6
ast/src/main/kotlin/gay/pizza/pork/ast/Declaration.kt
Normal file
@ -0,0 +1,6 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
sealed class Declaration : Node()
|
9
ast/src/main/kotlin/gay/pizza/pork/ast/Definition.kt
Normal file
9
ast/src/main/kotlin/gay/pizza/pork/ast/Definition.kt
Normal file
@ -0,0 +1,9 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
sealed class Definition : Node() {
|
||||
abstract val symbol: Symbol
|
||||
abstract val modifiers: DefinitionModifiers
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
class DefinitionModifiers(
|
||||
var export: Boolean
|
||||
)
|
6
ast/src/main/kotlin/gay/pizza/pork/ast/Expression.kt
Normal file
6
ast/src/main/kotlin/gay/pizza/pork/ast/Expression.kt
Normal file
@ -0,0 +1,6 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
sealed class Expression : Node()
|
25
ast/src/main/kotlin/gay/pizza/pork/ast/FunctionCall.kt
Normal file
25
ast/src/main/kotlin/gay/pizza/pork/ast/FunctionCall.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("functionCall")
|
||||
class FunctionCall(val symbol: Symbol, val arguments: List<Expression>) : Expression() {
|
||||
override val type: NodeType = NodeType.FunctionCall
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitAll(listOf(symbol), arguments)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is FunctionCall) return false
|
||||
return other.symbol == symbol && other.arguments == arguments
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = symbol.hashCode()
|
||||
result = 31 * result + arguments.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
31
ast/src/main/kotlin/gay/pizza/pork/ast/FunctionDefinition.kt
Normal file
31
ast/src/main/kotlin/gay/pizza/pork/ast/FunctionDefinition.kt
Normal file
@ -0,0 +1,31 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
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() {
|
||||
override val type: NodeType = NodeType.FunctionDeclaration
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitNodes(symbol)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is FunctionDefinition) return false
|
||||
return other.symbol == symbol && other.arguments == arguments && other.block == block
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = symbol.hashCode()
|
||||
result = 31 * result + arguments.hashCode()
|
||||
result = 31 * result + block.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
32
ast/src/main/kotlin/gay/pizza/pork/ast/If.kt
Normal file
32
ast/src/main/kotlin/gay/pizza/pork/ast/If.kt
Normal file
@ -0,0 +1,32 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("if")
|
||||
class If(
|
||||
val condition: Expression,
|
||||
val thenExpression: Expression,
|
||||
val elseExpression: Expression? = null
|
||||
) : Expression() {
|
||||
override val type: NodeType = NodeType.If
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitNodes(condition, thenExpression, elseExpression)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is If) return false
|
||||
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 + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
24
ast/src/main/kotlin/gay/pizza/pork/ast/ImportDeclaration.kt
Normal file
24
ast/src/main/kotlin/gay/pizza/pork/ast/ImportDeclaration.kt
Normal file
@ -0,0 +1,24 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("importDeclaration")
|
||||
class ImportDeclaration(val path: StringLiteral) : Declaration() {
|
||||
override val type: NodeType = NodeType.ImportDeclaration
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitNodes(path)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is ImportDeclaration) return false
|
||||
return other.path == path
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = path.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
32
ast/src/main/kotlin/gay/pizza/pork/ast/InfixOperation.kt
Normal file
32
ast/src/main/kotlin/gay/pizza/pork/ast/InfixOperation.kt
Normal file
@ -0,0 +1,32 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("infixOperation")
|
||||
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> =
|
||||
visitor.visitNodes(left, right)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is InfixOperation) return false
|
||||
return other.op == op &&
|
||||
other.left == left &&
|
||||
other.right == right
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = left.hashCode()
|
||||
result = 31 * result + op.hashCode()
|
||||
result = 31 * result + right.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
15
ast/src/main/kotlin/gay/pizza/pork/ast/InfixOperator.kt
Normal file
15
ast/src/main/kotlin/gay/pizza/pork/ast/InfixOperator.kt
Normal file
@ -0,0 +1,15 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("infixOperator")
|
||||
enum class InfixOperator(val token: String) {
|
||||
Plus("+"),
|
||||
Minus("-"),
|
||||
Multiply("*"),
|
||||
Divide("/"),
|
||||
Equals("=="),
|
||||
NotEquals("!=")
|
||||
}
|
21
ast/src/main/kotlin/gay/pizza/pork/ast/IntLiteral.kt
Normal file
21
ast/src/main/kotlin/gay/pizza/pork/ast/IntLiteral.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("intLiteral")
|
||||
class IntLiteral(val value: Int) : Expression() {
|
||||
override val type: NodeType = NodeType.IntLiteral
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is IntLiteral) return false
|
||||
return other.value == value
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = value
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
25
ast/src/main/kotlin/gay/pizza/pork/ast/Lambda.kt
Normal file
25
ast/src/main/kotlin/gay/pizza/pork/ast/Lambda.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("lambda")
|
||||
class Lambda(val arguments: List<Symbol>, val expressions: List<Expression>) : Expression() {
|
||||
override val type: NodeType = NodeType.Lambda
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitAll(arguments, expressions)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is Lambda) return false
|
||||
return other.arguments == arguments && other.expressions == expressions
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = arguments.hashCode()
|
||||
result = 31 * result + expressions.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
24
ast/src/main/kotlin/gay/pizza/pork/ast/ListLiteral.kt
Normal file
24
ast/src/main/kotlin/gay/pizza/pork/ast/ListLiteral.kt
Normal file
@ -0,0 +1,24 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("listLiteral")
|
||||
class ListLiteral(val items: List<Expression>) : Expression() {
|
||||
override val type: NodeType = NodeType.ListLiteral
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitAll(items)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is ListLiteral) return false
|
||||
return other.items == items
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = items.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
9
ast/src/main/kotlin/gay/pizza/pork/ast/Node.kt
Normal file
9
ast/src/main/kotlin/gay/pizza/pork/ast/Node.kt
Normal file
@ -0,0 +1,9 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
sealed class Node {
|
||||
abstract val type: NodeType
|
||||
open fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> = emptyList()
|
||||
}
|
27
ast/src/main/kotlin/gay/pizza/pork/ast/NodeCoalescer.kt
Normal file
27
ast/src/main/kotlin/gay/pizza/pork/ast/NodeCoalescer.kt
Normal file
@ -0,0 +1,27 @@
|
||||
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 visitDefine(node: Assignment): 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 visitCompilationUnit(node: CompilationUnit): Unit = handle(node)
|
||||
|
||||
private fun handle(node: Node) {
|
||||
handler(node)
|
||||
node.visitChildren(this)
|
||||
}
|
||||
}
|
42
ast/src/main/kotlin/gay/pizza/pork/ast/NodeType.kt
Normal file
42
ast/src/main/kotlin/gay/pizza/pork/ast/NodeType.kt
Normal file
@ -0,0 +1,42 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
enum class NodeType(val parent: NodeType? = null) {
|
||||
Node,
|
||||
Symbol(Node),
|
||||
Expression(Node),
|
||||
Declaration(Node),
|
||||
Block(Node),
|
||||
CompilationUnit(Node),
|
||||
IntLiteral(Expression),
|
||||
BooleanLiteral(Expression),
|
||||
ListLiteral(Expression),
|
||||
StringLiteral(Expression),
|
||||
Parentheses(Expression),
|
||||
Assignment(Expression),
|
||||
Lambda(Expression),
|
||||
PrefixOperation(Expression),
|
||||
InfixOperation(Expression),
|
||||
SymbolReference(Expression),
|
||||
FunctionCall(Expression),
|
||||
If(Expression),
|
||||
ImportDeclaration(Declaration),
|
||||
FunctionDeclaration(Declaration);
|
||||
|
||||
val parents: Set<NodeType>
|
||||
|
||||
init {
|
||||
val calculatedParents = mutableListOf<NodeType>()
|
||||
var self = this
|
||||
while (true) {
|
||||
calculatedParents.add(self)
|
||||
if (self.parent != null) {
|
||||
self = self.parent!!
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
parents = calculatedParents.toSet()
|
||||
}
|
||||
|
||||
fun isa(type: NodeType): Boolean = this == type || parents.contains(type)
|
||||
}
|
60
ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitor.kt
Normal file
60
ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitor.kt
Normal file
@ -0,0 +1,60 @@
|
||||
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 visitDefine(node: Assignment): 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 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 Assignment -> 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 visitDeclaration(node: Declaration): T = when (node) {
|
||||
is ImportDeclaration -> visitImportDeclaration(node)
|
||||
}
|
||||
|
||||
fun visitDefinition(node: Definition): T = when (node) {
|
||||
is FunctionDefinition -> visitFunctionDeclaration(node)
|
||||
}
|
||||
|
||||
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 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()
|
||||
}
|
24
ast/src/main/kotlin/gay/pizza/pork/ast/Parentheses.kt
Normal file
24
ast/src/main/kotlin/gay/pizza/pork/ast/Parentheses.kt
Normal file
@ -0,0 +1,24 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("parentheses")
|
||||
class Parentheses(val expression: Expression) : Expression() {
|
||||
override val type: NodeType = NodeType.Parentheses
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitNodes(expression)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is Parentheses) return false
|
||||
return other.expression == expression
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = expression.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
25
ast/src/main/kotlin/gay/pizza/pork/ast/PrefixOperation.kt
Normal file
25
ast/src/main/kotlin/gay/pizza/pork/ast/PrefixOperation.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("prefixOperation")
|
||||
class PrefixOperation(val op: PrefixOperator, val expression: Expression) : Expression() {
|
||||
override val type: NodeType = NodeType.PrefixOperation
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitNodes(expression)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is PrefixOperation) return false
|
||||
return other.op == op && other.expression == expression
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = op.hashCode()
|
||||
result = 31 * result + expression.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
10
ast/src/main/kotlin/gay/pizza/pork/ast/PrefixOperator.kt
Normal file
10
ast/src/main/kotlin/gay/pizza/pork/ast/PrefixOperator.kt
Normal file
@ -0,0 +1,10 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("prefixOperator")
|
||||
enum class PrefixOperator(val token: String) {
|
||||
Negate("!")
|
||||
}
|
21
ast/src/main/kotlin/gay/pizza/pork/ast/StringLiteral.kt
Normal file
21
ast/src/main/kotlin/gay/pizza/pork/ast/StringLiteral.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("stringLiteral")
|
||||
class StringLiteral(val text: String) : Expression() {
|
||||
override val type: NodeType = NodeType.StringLiteral
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is StringLiteral) return false
|
||||
return other.text == text
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = text.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
21
ast/src/main/kotlin/gay/pizza/pork/ast/Symbol.kt
Normal file
21
ast/src/main/kotlin/gay/pizza/pork/ast/Symbol.kt
Normal file
@ -0,0 +1,21 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("symbol")
|
||||
class Symbol(val id: String) : Node() {
|
||||
override val type: NodeType = NodeType.Symbol
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is Symbol) return false
|
||||
return other.id == id
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = id.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
24
ast/src/main/kotlin/gay/pizza/pork/ast/SymbolReference.kt
Normal file
24
ast/src/main/kotlin/gay/pizza/pork/ast/SymbolReference.kt
Normal file
@ -0,0 +1,24 @@
|
||||
package gay.pizza.pork.ast
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@SerialName("symbolReference")
|
||||
class SymbolReference(val symbol: Symbol) : Expression() {
|
||||
override val type: NodeType = NodeType.SymbolReference
|
||||
|
||||
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||
visitor.visitNodes(symbol)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is SymbolReference) return false
|
||||
return other.symbol == symbol
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = symbol.hashCode()
|
||||
result = 31 * result + type.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user