language: implement let definitions

This commit is contained in:
Alex Zenla 2023-09-11 04:57:13 -04:00
parent 5d53381b82
commit 8f60039d6e
Signed by: alex
GPG Key ID: C0780728420EBFE5
12 changed files with 95 additions and 8 deletions

View File

@ -137,6 +137,15 @@ types:
type: Block?
- name: native
type: Native?
LetDefinition:
parent: Definition
values:
- name: modifiers
type: DefinitionModifiers
- name: symbol
type: Symbol
- name: value
type: Expression
If:
parent: Expression
values:

View File

@ -16,6 +16,7 @@ digraph A {
type_FunctionCall [shape=box,label="FunctionCall"]
type_ArgumentSpec [shape=box,label="ArgumentSpec"]
type_FunctionDefinition [shape=box,label="FunctionDefinition"]
type_LetDefinition [shape=box,label="LetDefinition"]
type_If [shape=box,label="If"]
type_ImportDeclaration [shape=box,label="ImportDeclaration"]
type_IntegerLiteral [shape=box,label="IntegerLiteral"]
@ -58,6 +59,7 @@ digraph A {
type_Expression -> type_Break
type_Expression -> type_Continue
type_Definition -> type_FunctionDefinition
type_Definition -> type_LetDefinition
type_Declaration -> type_ImportDeclaration
type_Definition -> type_Symbol [style=dotted]
type_Definition -> type_DefinitionModifiers [style=dotted]
@ -80,6 +82,9 @@ digraph A {
type_FunctionDefinition -> type_ArgumentSpec [style=dotted]
type_FunctionDefinition -> type_Block [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_Block [style=dotted]
type_ImportDeclaration -> type_Symbol [style=dotted]

View 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
}
}

View File

@ -41,6 +41,9 @@ class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor<Unit> {
override fun visitLetAssignment(node: LetAssignment): Unit =
handle(node)
override fun visitLetDefinition(node: LetDefinition): Unit =
handle(node)
override fun visitListLiteral(node: ListLiteral): Unit =
handle(node)

View File

@ -19,6 +19,7 @@ enum class NodeType(val parent: NodeType? = null) {
InfixOperation(Expression),
IntegerLiteral(Expression),
LetAssignment(Expression),
LetDefinition(Definition),
ListLiteral(Expression),
Native(Node),
Parentheses(Expression),

View File

@ -28,6 +28,8 @@ interface NodeVisitor<T> {
fun visitLetAssignment(node: LetAssignment): T
fun visitLetDefinition(node: LetDefinition): T
fun visitListLiteral(node: ListLiteral): T
fun visitNative(node: Native): T

View File

@ -13,6 +13,7 @@ fun <T> NodeVisitor<T>.visit(node: Node): T =
is BooleanLiteral -> visitBooleanLiteral(node)
is FunctionCall -> visitFunctionCall(node)
is FunctionDefinition -> visitFunctionDefinition(node)
is LetDefinition -> visitLetDefinition(node)
is If -> visitIf(node)
is ImportDeclaration -> visitImportDeclaration(node)
is IntegerLiteral -> visitIntegerLiteral(node)

View File

@ -39,6 +39,10 @@ class CompilationUnitContext(
private fun definitionValue(definition: Definition): Any = when (definition) {
is FunctionDefinition -> FunctionContext(this, definition)
is LetDefinition -> {
EvaluationVisitor(internalScope.fork("let ${definition.symbol.id}"))
.visit(definition.value)
}
}
private fun processAllImports() {

View File

@ -30,6 +30,10 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
return value
}
override fun visitLetDefinition(node: LetDefinition): Any {
topLevelUsedError("LetDefinition", "CompilationUnitContext")
}
override fun visitSymbolReference(node: SymbolReference): Any =
currentScope.value(node.symbol.id)

View File

@ -1,7 +1,9 @@
let count = 5
export func main() {
var x = 1
while x <= 5 {
while x <= count {
println(x)
x = x + 1
x++
}
}

View File

@ -226,7 +226,7 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
ImportDeclaration(form, components)
}
private fun readFunctionDeclaration(): FunctionDefinition = within {
private fun readDefinitionModifiers(): DefinitionModifiers {
val modifiers = DefinitionModifiers(export = false)
while (true) {
val token = peek()
@ -238,12 +238,16 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
else -> break
}
}
return modifiers
}
private fun readFunctionDeclaration(modifiers: DefinitionModifiers): FunctionDefinition = within {
expect(TokenType.Func)
val name = readSymbolRaw()
expect(TokenType.LeftParentheses)
val arguments = collect(TokenType.RightParentheses, TokenType.Comma) {
val symbol = readSymbolRaw()
var multiple: Boolean = false
var multiple = false
if (next(TokenType.DotDotDot)) {
multiple = true
}
@ -261,11 +265,21 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
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? {
val modifiers = readDefinitionModifiers()
val token = peek()
return when (token.type) {
TokenType.Export,
TokenType.Func -> readFunctionDeclaration()
TokenType.Func -> readFunctionDeclaration(modifiers)
TokenType.Let -> readLetDefinition(modifiers)
else -> null
}
}

View File

@ -91,6 +91,14 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
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) {
visit(node.symbol)
}
@ -152,10 +160,14 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
visit(node.right)
}
override fun visitFunctionDefinition(node: FunctionDefinition) {
if (node.modifiers.export) {
private fun visitDefinitionModifiers(modifiers: DefinitionModifiers) {
if (modifiers.export) {
append("export ")
}
}
override fun visitFunctionDefinition(node: FunctionDefinition) {
visitDefinitionModifiers(node.modifiers)
append("func ")
visit(node.symbol)
append("(")