mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 21:21:33 +00:00
language: implement let definitions
This commit is contained in:
@ -137,6 +137,15 @@ types:
|
|||||||
type: Block?
|
type: Block?
|
||||||
- name: native
|
- name: native
|
||||||
type: Native?
|
type: Native?
|
||||||
|
LetDefinition:
|
||||||
|
parent: Definition
|
||||||
|
values:
|
||||||
|
- name: modifiers
|
||||||
|
type: DefinitionModifiers
|
||||||
|
- name: symbol
|
||||||
|
type: Symbol
|
||||||
|
- name: value
|
||||||
|
type: Expression
|
||||||
If:
|
If:
|
||||||
parent: Expression
|
parent: Expression
|
||||||
values:
|
values:
|
||||||
|
@ -16,6 +16,7 @@ digraph A {
|
|||||||
type_FunctionCall [shape=box,label="FunctionCall"]
|
type_FunctionCall [shape=box,label="FunctionCall"]
|
||||||
type_ArgumentSpec [shape=box,label="ArgumentSpec"]
|
type_ArgumentSpec [shape=box,label="ArgumentSpec"]
|
||||||
type_FunctionDefinition [shape=box,label="FunctionDefinition"]
|
type_FunctionDefinition [shape=box,label="FunctionDefinition"]
|
||||||
|
type_LetDefinition [shape=box,label="LetDefinition"]
|
||||||
type_If [shape=box,label="If"]
|
type_If [shape=box,label="If"]
|
||||||
type_ImportDeclaration [shape=box,label="ImportDeclaration"]
|
type_ImportDeclaration [shape=box,label="ImportDeclaration"]
|
||||||
type_IntegerLiteral [shape=box,label="IntegerLiteral"]
|
type_IntegerLiteral [shape=box,label="IntegerLiteral"]
|
||||||
@ -58,6 +59,7 @@ digraph A {
|
|||||||
type_Expression -> type_Break
|
type_Expression -> type_Break
|
||||||
type_Expression -> type_Continue
|
type_Expression -> type_Continue
|
||||||
type_Definition -> type_FunctionDefinition
|
type_Definition -> type_FunctionDefinition
|
||||||
|
type_Definition -> type_LetDefinition
|
||||||
type_Declaration -> type_ImportDeclaration
|
type_Declaration -> type_ImportDeclaration
|
||||||
type_Definition -> type_Symbol [style=dotted]
|
type_Definition -> type_Symbol [style=dotted]
|
||||||
type_Definition -> type_DefinitionModifiers [style=dotted]
|
type_Definition -> type_DefinitionModifiers [style=dotted]
|
||||||
@ -80,6 +82,9 @@ digraph A {
|
|||||||
type_FunctionDefinition -> type_ArgumentSpec [style=dotted]
|
type_FunctionDefinition -> type_ArgumentSpec [style=dotted]
|
||||||
type_FunctionDefinition -> type_Block [style=dotted]
|
type_FunctionDefinition -> type_Block [style=dotted]
|
||||||
type_FunctionDefinition -> type_Native [style=dotted]
|
type_FunctionDefinition -> type_Native [style=dotted]
|
||||||
|
type_LetDefinition -> type_DefinitionModifiers [style=dotted]
|
||||||
|
type_LetDefinition -> type_Symbol [style=dotted]
|
||||||
|
type_LetDefinition -> type_Expression [style=dotted]
|
||||||
type_If -> type_Expression [style=dotted]
|
type_If -> type_Expression [style=dotted]
|
||||||
type_If -> type_Block [style=dotted]
|
type_If -> type_Block [style=dotted]
|
||||||
type_ImportDeclaration -> type_Symbol [style=dotted]
|
type_ImportDeclaration -> type_Symbol [style=dotted]
|
||||||
|
30
ast/src/main/kotlin/gay/pizza/pork/ast/LetDefinition.kt
Normal file
30
ast/src/main/kotlin/gay/pizza/pork/ast/LetDefinition.kt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// GENERATED CODE FROM PORK AST CODEGEN
|
||||||
|
package gay.pizza.pork.ast
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("letDefinition")
|
||||||
|
class LetDefinition(override val modifiers: DefinitionModifiers, override val symbol: Symbol, val value: Expression) : Definition() {
|
||||||
|
override val type: NodeType = NodeType.LetDefinition
|
||||||
|
|
||||||
|
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||||
|
visitor.visitNodes(symbol, value)
|
||||||
|
|
||||||
|
override fun <T> visit(visitor: NodeVisitor<T>): T =
|
||||||
|
visitor.visitLetDefinition(this)
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is LetDefinition) return false
|
||||||
|
return other.modifiers == modifiers && other.symbol == symbol && other.value == value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = modifiers.hashCode()
|
||||||
|
result = 31 * result + symbol.hashCode()
|
||||||
|
result = 31 * result + value.hashCode()
|
||||||
|
result = 31 * result + type.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
@ -41,6 +41,9 @@ class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor<Unit> {
|
|||||||
override fun visitLetAssignment(node: LetAssignment): Unit =
|
override fun visitLetAssignment(node: LetAssignment): Unit =
|
||||||
handle(node)
|
handle(node)
|
||||||
|
|
||||||
|
override fun visitLetDefinition(node: LetDefinition): Unit =
|
||||||
|
handle(node)
|
||||||
|
|
||||||
override fun visitListLiteral(node: ListLiteral): Unit =
|
override fun visitListLiteral(node: ListLiteral): Unit =
|
||||||
handle(node)
|
handle(node)
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ enum class NodeType(val parent: NodeType? = null) {
|
|||||||
InfixOperation(Expression),
|
InfixOperation(Expression),
|
||||||
IntegerLiteral(Expression),
|
IntegerLiteral(Expression),
|
||||||
LetAssignment(Expression),
|
LetAssignment(Expression),
|
||||||
|
LetDefinition(Definition),
|
||||||
ListLiteral(Expression),
|
ListLiteral(Expression),
|
||||||
Native(Node),
|
Native(Node),
|
||||||
Parentheses(Expression),
|
Parentheses(Expression),
|
||||||
|
@ -28,6 +28,8 @@ interface NodeVisitor<T> {
|
|||||||
|
|
||||||
fun visitLetAssignment(node: LetAssignment): T
|
fun visitLetAssignment(node: LetAssignment): T
|
||||||
|
|
||||||
|
fun visitLetDefinition(node: LetDefinition): T
|
||||||
|
|
||||||
fun visitListLiteral(node: ListLiteral): T
|
fun visitListLiteral(node: ListLiteral): T
|
||||||
|
|
||||||
fun visitNative(node: Native): T
|
fun visitNative(node: Native): T
|
||||||
|
@ -13,6 +13,7 @@ fun <T> NodeVisitor<T>.visit(node: Node): T =
|
|||||||
is BooleanLiteral -> visitBooleanLiteral(node)
|
is BooleanLiteral -> visitBooleanLiteral(node)
|
||||||
is FunctionCall -> visitFunctionCall(node)
|
is FunctionCall -> visitFunctionCall(node)
|
||||||
is FunctionDefinition -> visitFunctionDefinition(node)
|
is FunctionDefinition -> visitFunctionDefinition(node)
|
||||||
|
is LetDefinition -> visitLetDefinition(node)
|
||||||
is If -> visitIf(node)
|
is If -> visitIf(node)
|
||||||
is ImportDeclaration -> visitImportDeclaration(node)
|
is ImportDeclaration -> visitImportDeclaration(node)
|
||||||
is IntegerLiteral -> visitIntegerLiteral(node)
|
is IntegerLiteral -> visitIntegerLiteral(node)
|
||||||
|
@ -39,6 +39,10 @@ class CompilationUnitContext(
|
|||||||
|
|
||||||
private fun definitionValue(definition: Definition): Any = when (definition) {
|
private fun definitionValue(definition: Definition): Any = when (definition) {
|
||||||
is FunctionDefinition -> FunctionContext(this, definition)
|
is FunctionDefinition -> FunctionContext(this, definition)
|
||||||
|
is LetDefinition -> {
|
||||||
|
EvaluationVisitor(internalScope.fork("let ${definition.symbol.id}"))
|
||||||
|
.visit(definition.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processAllImports() {
|
private fun processAllImports() {
|
||||||
|
@ -30,6 +30,10 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitLetDefinition(node: LetDefinition): Any {
|
||||||
|
topLevelUsedError("LetDefinition", "CompilationUnitContext")
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitSymbolReference(node: SymbolReference): Any =
|
override fun visitSymbolReference(node: SymbolReference): Any =
|
||||||
currentScope.value(node.symbol.id)
|
currentScope.value(node.symbol.id)
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
let count = 5
|
||||||
|
|
||||||
export func main() {
|
export func main() {
|
||||||
var x = 1
|
var x = 1
|
||||||
while x <= 5 {
|
while x <= count {
|
||||||
println(x)
|
println(x)
|
||||||
x = x + 1
|
x++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
ImportDeclaration(form, components)
|
ImportDeclaration(form, components)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readFunctionDeclaration(): FunctionDefinition = within {
|
private fun readDefinitionModifiers(): DefinitionModifiers {
|
||||||
val modifiers = DefinitionModifiers(export = false)
|
val modifiers = DefinitionModifiers(export = false)
|
||||||
while (true) {
|
while (true) {
|
||||||
val token = peek()
|
val token = peek()
|
||||||
@ -238,12 +238,16 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
else -> break
|
else -> break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return modifiers
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun readFunctionDeclaration(modifiers: DefinitionModifiers): FunctionDefinition = within {
|
||||||
expect(TokenType.Func)
|
expect(TokenType.Func)
|
||||||
val name = readSymbolRaw()
|
val name = readSymbolRaw()
|
||||||
expect(TokenType.LeftParentheses)
|
expect(TokenType.LeftParentheses)
|
||||||
val arguments = collect(TokenType.RightParentheses, TokenType.Comma) {
|
val arguments = collect(TokenType.RightParentheses, TokenType.Comma) {
|
||||||
val symbol = readSymbolRaw()
|
val symbol = readSymbolRaw()
|
||||||
var multiple: Boolean = false
|
var multiple = false
|
||||||
if (next(TokenType.DotDotDot)) {
|
if (next(TokenType.DotDotDot)) {
|
||||||
multiple = true
|
multiple = true
|
||||||
}
|
}
|
||||||
@ -261,11 +265,21 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
FunctionDefinition(modifiers, name, arguments, block, native)
|
FunctionDefinition(modifiers, name, arguments, block, native)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun readLetDefinition(modifiers: DefinitionModifiers): LetDefinition = within {
|
||||||
|
val modifiers = readDefinitionModifiers()
|
||||||
|
expect(TokenType.Let)
|
||||||
|
val name = readSymbolRaw()
|
||||||
|
expect(TokenType.Equals)
|
||||||
|
val value = readExpression()
|
||||||
|
LetDefinition(modifiers, name, value)
|
||||||
|
}
|
||||||
|
|
||||||
private fun maybeReadDefinition(): Definition? {
|
private fun maybeReadDefinition(): Definition? {
|
||||||
|
val modifiers = readDefinitionModifiers()
|
||||||
val token = peek()
|
val token = peek()
|
||||||
return when (token.type) {
|
return when (token.type) {
|
||||||
TokenType.Export,
|
TokenType.Func -> readFunctionDeclaration(modifiers)
|
||||||
TokenType.Func -> readFunctionDeclaration()
|
TokenType.Let -> readLetDefinition(modifiers)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,14 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
|
|||||||
visit(node.value)
|
visit(node.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitLetDefinition(node: LetDefinition) {
|
||||||
|
visitDefinitionModifiers(node.modifiers)
|
||||||
|
append("let ")
|
||||||
|
visit(node.symbol)
|
||||||
|
append(" = ")
|
||||||
|
visit(node.value)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitSymbolReference(node: SymbolReference) {
|
override fun visitSymbolReference(node: SymbolReference) {
|
||||||
visit(node.symbol)
|
visit(node.symbol)
|
||||||
}
|
}
|
||||||
@ -152,10 +160,14 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
|
|||||||
visit(node.right)
|
visit(node.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunctionDefinition(node: FunctionDefinition) {
|
private fun visitDefinitionModifiers(modifiers: DefinitionModifiers) {
|
||||||
if (node.modifiers.export) {
|
if (modifiers.export) {
|
||||||
append("export ")
|
append("export ")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunctionDefinition(node: FunctionDefinition) {
|
||||||
|
visitDefinitionModifiers(node.modifiers)
|
||||||
append("func ")
|
append("func ")
|
||||||
visit(node.symbol)
|
visit(node.symbol)
|
||||||
append("(")
|
append("(")
|
||||||
|
Reference in New Issue
Block a user