diff --git a/src/main/kotlin/gay/pizza/pork/ast/Define.kt b/src/main/kotlin/gay/pizza/pork/ast/Define.kt deleted file mode 100644 index 3e96a4a..0000000 --- a/src/main/kotlin/gay/pizza/pork/ast/Define.kt +++ /dev/null @@ -1,8 +0,0 @@ -package gay.pizza.pork.ast - -class Define(val symbol: Symbol, val value: Expression) : Expression() { - override val type: NodeType = NodeType.Define - - override fun visitChildren(visitor: Visitor): List = - visitor.visitNodes(symbol, value) -} diff --git a/src/main/kotlin/gay/pizza/pork/ast/ListLiteral.kt b/src/main/kotlin/gay/pizza/pork/ast/ListLiteral.kt deleted file mode 100644 index d0b094c..0000000 --- a/src/main/kotlin/gay/pizza/pork/ast/ListLiteral.kt +++ /dev/null @@ -1,8 +0,0 @@ -package gay.pizza.pork.ast - -class ListLiteral(val items: List) : Expression() { - override val type: NodeType = NodeType.ListLiteral - - override fun visitChildren(visitor: Visitor): List = - visitor.visitAll(items) -} diff --git a/src/main/kotlin/gay/pizza/pork/ast/Node.kt b/src/main/kotlin/gay/pizza/pork/ast/Node.kt deleted file mode 100644 index 9919bb1..0000000 --- a/src/main/kotlin/gay/pizza/pork/ast/Node.kt +++ /dev/null @@ -1,8 +0,0 @@ -package gay.pizza.pork.ast - -abstract class Node { - abstract val type: NodeType - open fun visitChildren(visitor: Visitor): List = emptyList() - - override fun toString(): String = let { node -> buildString { Printer(this).visit(node) } } -} diff --git a/src/main/kotlin/gay/pizza/pork/ast/NodeCoalescer.kt b/src/main/kotlin/gay/pizza/pork/ast/NodeCoalescer.kt new file mode 100644 index 0000000..8fad95b --- /dev/null +++ b/src/main/kotlin/gay/pizza/pork/ast/NodeCoalescer.kt @@ -0,0 +1,19 @@ +package gay.pizza.pork.ast + +import gay.pizza.pork.ast.nodes.* + +class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor { + 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 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) +} diff --git a/src/main/kotlin/gay/pizza/pork/ast/Visitor.kt b/src/main/kotlin/gay/pizza/pork/ast/NodeVisitor.kt similarity index 96% rename from src/main/kotlin/gay/pizza/pork/ast/Visitor.kt rename to src/main/kotlin/gay/pizza/pork/ast/NodeVisitor.kt index 6e4fdfe..a2e9cfb 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/Visitor.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/NodeVisitor.kt @@ -1,6 +1,8 @@ package gay.pizza.pork.ast -interface Visitor { +import gay.pizza.pork.ast.nodes.* + +interface NodeVisitor { fun visitDefine(node: Define): T fun visitFunctionCall(node: FunctionCall): T fun visitReference(node: SymbolReference): T diff --git a/src/main/kotlin/gay/pizza/pork/ast/Parentheses.kt b/src/main/kotlin/gay/pizza/pork/ast/Parentheses.kt deleted file mode 100644 index 8b455dd..0000000 --- a/src/main/kotlin/gay/pizza/pork/ast/Parentheses.kt +++ /dev/null @@ -1,8 +0,0 @@ -package gay.pizza.pork.ast - -class Parentheses(val expression: Expression) : Expression() { - override val type: NodeType = NodeType.Parentheses - - override fun visitChildren(visitor: Visitor): List = - visitor.visitNodes(expression) -} diff --git a/src/main/kotlin/gay/pizza/pork/ast/Printer.kt b/src/main/kotlin/gay/pizza/pork/ast/Printer.kt index 824c8e0..1022f46 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/Printer.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/Printer.kt @@ -1,6 +1,8 @@ package gay.pizza.pork.ast -class Printer(private val buffer: StringBuilder) : Visitor { +import gay.pizza.pork.ast.nodes.* + +class Printer(private val buffer: StringBuilder) : NodeVisitor { private var indent = 0 private fun append(text: String) { @@ -65,6 +67,8 @@ class Printer(private val buffer: StringBuilder) : Visitor { } append(" ") } + } else { + append(" ") } append("in") indent++ diff --git a/src/main/kotlin/gay/pizza/pork/ast/Program.kt b/src/main/kotlin/gay/pizza/pork/ast/Program.kt deleted file mode 100644 index bad04fc..0000000 --- a/src/main/kotlin/gay/pizza/pork/ast/Program.kt +++ /dev/null @@ -1,8 +0,0 @@ -package gay.pizza.pork.ast - -class Program(val expressions: List) : Node() { - override val type: NodeType = NodeType.Program - - override fun visitChildren(visitor: Visitor): List = - visitor.visitAll(expressions) -} diff --git a/src/main/kotlin/gay/pizza/pork/ast/SymbolReference.kt b/src/main/kotlin/gay/pizza/pork/ast/SymbolReference.kt deleted file mode 100644 index 04e4e82..0000000 --- a/src/main/kotlin/gay/pizza/pork/ast/SymbolReference.kt +++ /dev/null @@ -1,8 +0,0 @@ -package gay.pizza.pork.ast - -class SymbolReference(val symbol: Symbol) : Expression() { - override val type: NodeType = NodeType.SymbolReference - - override fun visitChildren(visitor: Visitor): List = - visitor.visitNodes(symbol) -} diff --git a/src/main/kotlin/gay/pizza/pork/ast/BooleanLiteral.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/BooleanLiteral.kt similarity index 62% rename from src/main/kotlin/gay/pizza/pork/ast/BooleanLiteral.kt rename to src/main/kotlin/gay/pizza/pork/ast/nodes/BooleanLiteral.kt index 244550a..28d95b9 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/BooleanLiteral.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/BooleanLiteral.kt @@ -1,4 +1,6 @@ -package gay.pizza.pork.ast +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType class BooleanLiteral(val value: Boolean) : Expression() { override val type: NodeType = NodeType.BooleanLiteral diff --git a/src/main/kotlin/gay/pizza/pork/ast/nodes/Define.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/Define.kt new file mode 100644 index 0000000..0b0bb5d --- /dev/null +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/Define.kt @@ -0,0 +1,11 @@ +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType +import gay.pizza.pork.ast.NodeVisitor + +class Define(val symbol: Symbol, val value: Expression) : Expression() { + override val type: NodeType = NodeType.Define + + override fun visitChildren(visitor: NodeVisitor): List = + visitor.visitNodes(symbol, value) +} diff --git a/src/main/kotlin/gay/pizza/pork/ast/Expression.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/Expression.kt similarity index 52% rename from src/main/kotlin/gay/pizza/pork/ast/Expression.kt rename to src/main/kotlin/gay/pizza/pork/ast/nodes/Expression.kt index 916bf7d..a32dfbc 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/Expression.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/Expression.kt @@ -1,3 +1,3 @@ -package gay.pizza.pork.ast +package gay.pizza.pork.ast.nodes abstract class Expression : Node() diff --git a/src/main/kotlin/gay/pizza/pork/ast/FunctionCall.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/FunctionCall.kt similarity index 52% rename from src/main/kotlin/gay/pizza/pork/ast/FunctionCall.kt rename to src/main/kotlin/gay/pizza/pork/ast/nodes/FunctionCall.kt index e9baee6..67ad888 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/FunctionCall.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/FunctionCall.kt @@ -1,8 +1,11 @@ -package gay.pizza.pork.ast +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType +import gay.pizza.pork.ast.NodeVisitor class FunctionCall(val symbol: Symbol, val arguments: List) : Expression() { override val type: NodeType = NodeType.FunctionCall - override fun visitChildren(visitor: Visitor): List = + override fun visitChildren(visitor: NodeVisitor): List = visitor.visitAll(listOf(symbol), arguments) } diff --git a/src/main/kotlin/gay/pizza/pork/ast/If.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/If.kt similarity index 72% rename from src/main/kotlin/gay/pizza/pork/ast/If.kt rename to src/main/kotlin/gay/pizza/pork/ast/nodes/If.kt index 3a8b98b..39ccbe7 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/If.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/If.kt @@ -1,4 +1,6 @@ -package gay.pizza.pork.ast +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType class If( val condition: Expression, diff --git a/src/main/kotlin/gay/pizza/pork/ast/InfixOperation.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/InfixOperation.kt similarity index 53% rename from src/main/kotlin/gay/pizza/pork/ast/InfixOperation.kt rename to src/main/kotlin/gay/pizza/pork/ast/nodes/InfixOperation.kt index 9d2b74c..e863664 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/InfixOperation.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/InfixOperation.kt @@ -1,8 +1,11 @@ -package gay.pizza.pork.ast +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType +import gay.pizza.pork.ast.NodeVisitor class InfixOperation(val left: Expression, val op: InfixOperator, val right: Expression) : Expression() { override val type: NodeType = NodeType.InfixOperation - override fun visitChildren(visitor: Visitor): List = + override fun visitChildren(visitor: NodeVisitor): List = visitor.visitNodes(left, right) } diff --git a/src/main/kotlin/gay/pizza/pork/ast/InfixOperator.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/InfixOperator.kt similarity index 78% rename from src/main/kotlin/gay/pizza/pork/ast/InfixOperator.kt rename to src/main/kotlin/gay/pizza/pork/ast/nodes/InfixOperator.kt index 0d015c2..776b636 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/InfixOperator.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/InfixOperator.kt @@ -1,4 +1,4 @@ -package gay.pizza.pork.ast +package gay.pizza.pork.ast.nodes enum class InfixOperator(val token: String) { Plus("+"), diff --git a/src/main/kotlin/gay/pizza/pork/ast/IntLiteral.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/IntLiteral.kt similarity index 60% rename from src/main/kotlin/gay/pizza/pork/ast/IntLiteral.kt rename to src/main/kotlin/gay/pizza/pork/ast/nodes/IntLiteral.kt index 7175336..af2e034 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/IntLiteral.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/IntLiteral.kt @@ -1,4 +1,6 @@ -package gay.pizza.pork.ast +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType class IntLiteral(val value: Int) : Expression() { override val type: NodeType = NodeType.IntLiteral diff --git a/src/main/kotlin/gay/pizza/pork/ast/Lambda.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/Lambda.kt similarity index 52% rename from src/main/kotlin/gay/pizza/pork/ast/Lambda.kt rename to src/main/kotlin/gay/pizza/pork/ast/nodes/Lambda.kt index 0b73601..0b92492 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/Lambda.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/Lambda.kt @@ -1,8 +1,11 @@ -package gay.pizza.pork.ast +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType +import gay.pizza.pork.ast.NodeVisitor class Lambda(val arguments: List, val expressions: List) : Expression() { override val type: NodeType = NodeType.Lambda - override fun visitChildren(visitor: Visitor): List = + override fun visitChildren(visitor: NodeVisitor): List = visitor.visitAll(arguments, expressions) } diff --git a/src/main/kotlin/gay/pizza/pork/ast/nodes/ListLiteral.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/ListLiteral.kt new file mode 100644 index 0000000..2685e99 --- /dev/null +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/ListLiteral.kt @@ -0,0 +1,11 @@ +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType +import gay.pizza.pork.ast.NodeVisitor + +class ListLiteral(val items: List) : Expression() { + override val type: NodeType = NodeType.ListLiteral + + override fun visitChildren(visitor: NodeVisitor): List = + visitor.visitAll(items) +} diff --git a/src/main/kotlin/gay/pizza/pork/ast/nodes/Node.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/Node.kt new file mode 100644 index 0000000..1cfbb72 --- /dev/null +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/Node.kt @@ -0,0 +1,12 @@ +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType +import gay.pizza.pork.ast.Printer +import gay.pizza.pork.ast.NodeVisitor + +abstract class Node { + abstract val type: NodeType + open fun visitChildren(visitor: NodeVisitor): List = emptyList() + + override fun toString(): String = let { node -> buildString { Printer(this).visit(node) } } +} diff --git a/src/main/kotlin/gay/pizza/pork/ast/nodes/Parentheses.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/Parentheses.kt new file mode 100644 index 0000000..9bb8e6c --- /dev/null +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/Parentheses.kt @@ -0,0 +1,11 @@ +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType +import gay.pizza.pork.ast.NodeVisitor + +class Parentheses(val expression: Expression) : Expression() { + override val type: NodeType = NodeType.Parentheses + + override fun visitChildren(visitor: NodeVisitor): List = + visitor.visitNodes(expression) +} diff --git a/src/main/kotlin/gay/pizza/pork/ast/PrefixOperation.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/PrefixOperation.kt similarity index 68% rename from src/main/kotlin/gay/pizza/pork/ast/PrefixOperation.kt rename to src/main/kotlin/gay/pizza/pork/ast/nodes/PrefixOperation.kt index f184d4a..24c0b3a 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/PrefixOperation.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/PrefixOperation.kt @@ -1,4 +1,6 @@ -package gay.pizza.pork.ast +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType class PrefixOperation(val op: PrefixOperator, val expression: Expression) : Expression() { override val type: NodeType = NodeType.PrefixOperation diff --git a/src/main/kotlin/gay/pizza/pork/ast/PrefixOperator.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/PrefixOperator.kt similarity index 65% rename from src/main/kotlin/gay/pizza/pork/ast/PrefixOperator.kt rename to src/main/kotlin/gay/pizza/pork/ast/nodes/PrefixOperator.kt index 5da19e5..7bd9d75 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/PrefixOperator.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/PrefixOperator.kt @@ -1,4 +1,4 @@ -package gay.pizza.pork.ast +package gay.pizza.pork.ast.nodes enum class PrefixOperator(val token: String) { Negate("!") diff --git a/src/main/kotlin/gay/pizza/pork/ast/nodes/Program.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/Program.kt new file mode 100644 index 0000000..1871444 --- /dev/null +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/Program.kt @@ -0,0 +1,11 @@ +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType +import gay.pizza.pork.ast.NodeVisitor + +class Program(val expressions: List) : Node() { + override val type: NodeType = NodeType.Program + + override fun visitChildren(visitor: NodeVisitor): List = + visitor.visitAll(expressions) +} diff --git a/src/main/kotlin/gay/pizza/pork/ast/Symbol.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/Symbol.kt similarity index 56% rename from src/main/kotlin/gay/pizza/pork/ast/Symbol.kt rename to src/main/kotlin/gay/pizza/pork/ast/nodes/Symbol.kt index 5c32a1c..1cad7ae 100644 --- a/src/main/kotlin/gay/pizza/pork/ast/Symbol.kt +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/Symbol.kt @@ -1,4 +1,6 @@ -package gay.pizza.pork.ast +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType class Symbol(val id: String) : Node() { override val type: NodeType = NodeType.Symbol diff --git a/src/main/kotlin/gay/pizza/pork/ast/nodes/SymbolReference.kt b/src/main/kotlin/gay/pizza/pork/ast/nodes/SymbolReference.kt new file mode 100644 index 0000000..78816d2 --- /dev/null +++ b/src/main/kotlin/gay/pizza/pork/ast/nodes/SymbolReference.kt @@ -0,0 +1,11 @@ +package gay.pizza.pork.ast.nodes + +import gay.pizza.pork.ast.NodeType +import gay.pizza.pork.ast.NodeVisitor + +class SymbolReference(val symbol: Symbol) : Expression() { + override val type: NodeType = NodeType.SymbolReference + + override fun visitChildren(visitor: NodeVisitor): List = + visitor.visitNodes(symbol) +} diff --git a/src/main/kotlin/gay/pizza/pork/compiler/KotlinCompiler.kt b/src/main/kotlin/gay/pizza/pork/compiler/KotlinCompiler.kt index 311019f..1b2dd81 100644 --- a/src/main/kotlin/gay/pizza/pork/compiler/KotlinCompiler.kt +++ b/src/main/kotlin/gay/pizza/pork/compiler/KotlinCompiler.kt @@ -1,8 +1,9 @@ package gay.pizza.pork.compiler import gay.pizza.pork.ast.* +import gay.pizza.pork.ast.nodes.* -class KotlinCompiler : Visitor { +class KotlinCompiler : NodeVisitor { override fun visitDefine(node: Define): String = "val ${visit(node.symbol)} = ${visit(node.value)}" diff --git a/src/main/kotlin/gay/pizza/pork/eval/PorkEvaluator.kt b/src/main/kotlin/gay/pizza/pork/eval/PorkEvaluator.kt index ff2a668..2837db0 100644 --- a/src/main/kotlin/gay/pizza/pork/eval/PorkEvaluator.kt +++ b/src/main/kotlin/gay/pizza/pork/eval/PorkEvaluator.kt @@ -1,8 +1,9 @@ package gay.pizza.pork.eval import gay.pizza.pork.ast.* +import gay.pizza.pork.ast.nodes.* -class PorkEvaluator(root: Scope) : Visitor { +class PorkEvaluator(root: Scope) : NodeVisitor { private var currentScope: Scope = root override fun visitDefine(node: Define): Any { diff --git a/src/main/kotlin/gay/pizza/pork/main.kt b/src/main/kotlin/gay/pizza/pork/main.kt index a48d452..1971cf4 100644 --- a/src/main/kotlin/gay/pizza/pork/main.kt +++ b/src/main/kotlin/gay/pizza/pork/main.kt @@ -1,6 +1,7 @@ package gay.pizza.pork -import gay.pizza.pork.ast.Program +import gay.pizza.pork.ast.Printer +import gay.pizza.pork.ast.nodes.Program import gay.pizza.pork.eval.Arguments import gay.pizza.pork.eval.PorkEvaluator import gay.pizza.pork.eval.Scope @@ -39,9 +40,14 @@ fun main(args: Array) { eval(program) val exactCode = stream.tokens.joinToString("") { it.text } - println(exactCode) - println(code == exactCode) validateTokenSoundness(code, stream) + if (exactCode != code) { + throw RuntimeException("Token reconstruction didn't succeed.") + } + + val generated = buildString { Printer(this).visit(program) } + parse(tokenize(generated)) + println(generated) } fun tokenize(input: String): TokenStream = diff --git a/src/main/kotlin/gay/pizza/pork/parse/PorkParser.kt b/src/main/kotlin/gay/pizza/pork/parse/PorkParser.kt index ff3fc24..0425c07 100644 --- a/src/main/kotlin/gay/pizza/pork/parse/PorkParser.kt +++ b/src/main/kotlin/gay/pizza/pork/parse/PorkParser.kt @@ -1,6 +1,6 @@ package gay.pizza.pork.parse -import gay.pizza.pork.ast.* +import gay.pizza.pork.ast.nodes.* class PorkParser(source: PeekableSource) { private val whitespaceIncludedSource = source