From 1b363dcf569ed527e54cf140f6a30bdb61ef1b1b Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Tue, 12 Sep 2023 00:25:13 -0400 Subject: [PATCH] parser: implement long literal and handle overflow --- ast/src/main/ast/pork.yml | 5 ++++ ast/src/main/graph/types.dot | 2 ++ .../kotlin/gay/pizza/pork/ast/LongLiteral.kt | 25 +++++++++++++++++++ .../gay/pizza/pork/ast/NodeCoalescer.kt | 3 +++ .../kotlin/gay/pizza/pork/ast/NodeType.kt | 1 + .../kotlin/gay/pizza/pork/ast/NodeVisitor.kt | 2 ++ .../pizza/pork/ast/NodeVisitorExtensions.kt | 1 + .../pizza/pork/buildext/ast/AstPrimitive.kt | 1 + .../pizza/pork/evaluator/EvaluationVisitor.kt | 2 ++ .../kotlin/gay/pizza/pork/parser/Parser.kt | 10 +++++++- .../kotlin/gay/pizza/pork/parser/Printer.kt | 4 +++ .../pizza/pork/idea/PorkSymbolDeclaration.kt | 1 - 12 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 ast/src/main/kotlin/gay/pizza/pork/ast/LongLiteral.kt diff --git a/ast/src/main/ast/pork.yml b/ast/src/main/ast/pork.yml index d684c27..8933d21 100644 --- a/ast/src/main/ast/pork.yml +++ b/ast/src/main/ast/pork.yml @@ -182,6 +182,11 @@ types: values: - name: value type: Int + LongLiteral: + parent: Expression + values: + - name: value + type: Long DoubleLiteral: parent: Expression values: diff --git a/ast/src/main/graph/types.dot b/ast/src/main/graph/types.dot index 0bd1e5e..d56d0eb 100644 --- a/ast/src/main/graph/types.dot +++ b/ast/src/main/graph/types.dot @@ -20,6 +20,7 @@ digraph A { type_If [shape=box,label="If"] type_ImportDeclaration [shape=box,label="ImportDeclaration"] type_IntegerLiteral [shape=box,label="IntegerLiteral"] + type_LongLiteral [shape=box,label="LongLiteral"] type_DoubleLiteral [shape=box,label="DoubleLiteral"] type_ListLiteral [shape=box,label="ListLiteral"] type_Parentheses [shape=box,label="Parentheses"] @@ -49,6 +50,7 @@ digraph A { type_Expression -> type_FunctionCall type_Expression -> type_If type_Expression -> type_IntegerLiteral + type_Expression -> type_LongLiteral type_Expression -> type_DoubleLiteral type_Expression -> type_ListLiteral type_Expression -> type_Parentheses diff --git a/ast/src/main/kotlin/gay/pizza/pork/ast/LongLiteral.kt b/ast/src/main/kotlin/gay/pizza/pork/ast/LongLiteral.kt new file mode 100644 index 0000000..fe737e5 --- /dev/null +++ b/ast/src/main/kotlin/gay/pizza/pork/ast/LongLiteral.kt @@ -0,0 +1,25 @@ +// GENERATED CODE FROM PORK AST CODEGEN +package gay.pizza.pork.ast + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@SerialName("longLiteral") +class LongLiteral(val value: Long) : Expression() { + override val type: NodeType = NodeType.LongLiteral + + override fun visit(visitor: NodeVisitor): T = + visitor.visitLongLiteral(this) + + override fun equals(other: Any?): Boolean { + if (other !is LongLiteral) return false + return other.value == value + } + + override fun hashCode(): Int { + var result = value.hashCode() + result = 31 * result + type.hashCode() + return result + } +} diff --git a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeCoalescer.kt b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeCoalescer.kt index ba45370..e244746 100644 --- a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeCoalescer.kt +++ b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeCoalescer.kt @@ -50,6 +50,9 @@ class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor { override fun visitListLiteral(node: ListLiteral): Unit = handle(node) + override fun visitLongLiteral(node: LongLiteral): Unit = + handle(node) + override fun visitNative(node: Native): Unit = handle(node) diff --git a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeType.kt b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeType.kt index 8860bdc..d5ca830 100644 --- a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeType.kt +++ b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeType.kt @@ -22,6 +22,7 @@ enum class NodeType(val parent: NodeType? = null) { LetAssignment(Expression), LetDefinition(Definition), ListLiteral(Expression), + LongLiteral(Expression), Native(Node), Parentheses(Expression), PrefixOperation(Expression), diff --git a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitor.kt b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitor.kt index faff876..dd04374 100644 --- a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitor.kt +++ b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitor.kt @@ -34,6 +34,8 @@ interface NodeVisitor { fun visitListLiteral(node: ListLiteral): T + fun visitLongLiteral(node: LongLiteral): T + fun visitNative(node: Native): T fun visitParentheses(node: Parentheses): T diff --git a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitorExtensions.kt b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitorExtensions.kt index 8d45fbd..818bb66 100644 --- a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitorExtensions.kt +++ b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitorExtensions.kt @@ -17,6 +17,7 @@ fun NodeVisitor.visit(node: Node): T = is If -> visitIf(node) is ImportDeclaration -> visitImportDeclaration(node) is IntegerLiteral -> visitIntegerLiteral(node) + is LongLiteral -> visitLongLiteral(node) is DoubleLiteral -> visitDoubleLiteral(node) is ListLiteral -> visitListLiteral(node) is Parentheses -> visitParentheses(node) diff --git a/buildext/src/main/kotlin/gay/pizza/pork/buildext/ast/AstPrimitive.kt b/buildext/src/main/kotlin/gay/pizza/pork/buildext/ast/AstPrimitive.kt index 331fad6..8ceb57c 100644 --- a/buildext/src/main/kotlin/gay/pizza/pork/buildext/ast/AstPrimitive.kt +++ b/buildext/src/main/kotlin/gay/pizza/pork/buildext/ast/AstPrimitive.kt @@ -4,5 +4,6 @@ enum class AstPrimitive(val id: kotlin.String) { Boolean("Boolean"), String("String"), Int("Int"), + Long("Long"), Double("Double") } diff --git a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/EvaluationVisitor.kt b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/EvaluationVisitor.kt index 1e3c6b6..aacabb6 100644 --- a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/EvaluationVisitor.kt +++ b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/EvaluationVisitor.kt @@ -39,6 +39,8 @@ class EvaluationVisitor(root: Scope) : NodeVisitor { override fun visitListLiteral(node: ListLiteral): Any = node.items.map { it.visit(this) } + override fun visitLongLiteral(node: LongLiteral): Any = node.value + override fun visitSymbol(node: Symbol): Any = None override fun visitFunctionCall(node: FunctionCall): Any { diff --git a/parser/src/main/kotlin/gay/pizza/pork/parser/Parser.kt b/parser/src/main/kotlin/gay/pizza/pork/parser/Parser.kt index f09b662..d69869c 100644 --- a/parser/src/main/kotlin/gay/pizza/pork/parser/Parser.kt +++ b/parser/src/main/kotlin/gay/pizza/pork/parser/Parser.kt @@ -11,7 +11,15 @@ class Parser(source: PeekableSource, val attribution: NodeAttribution) { if (it.text.contains(".")) { DoubleLiteral(it.text.toDouble()) } else { - IntegerLiteral(it.text.toInt()) + val integer = it.text.toIntOrNull() + if (integer != null) { + IntegerLiteral(integer) + } + val long = it.text.toLongOrNull() + if (long != null) { + LongLiteral(long) + } + throw ParseError("Illegal integer value") } } } diff --git a/parser/src/main/kotlin/gay/pizza/pork/parser/Printer.kt b/parser/src/main/kotlin/gay/pizza/pork/parser/Printer.kt index 146ebb7..b7fd6d5 100644 --- a/parser/src/main/kotlin/gay/pizza/pork/parser/Printer.kt +++ b/parser/src/main/kotlin/gay/pizza/pork/parser/Printer.kt @@ -70,6 +70,10 @@ class Printer(buffer: StringBuilder) : NodeVisitor { append("]") } + override fun visitLongLiteral(node: LongLiteral) { + append(node.value.toString()) + } + override fun visitNative(node: Native) { append("native ") visit(node.form) diff --git a/support/pork-idea/src/main/kotlin/gay/pizza/pork/idea/PorkSymbolDeclaration.kt b/support/pork-idea/src/main/kotlin/gay/pizza/pork/idea/PorkSymbolDeclaration.kt index 256cbfe..a5397f9 100644 --- a/support/pork-idea/src/main/kotlin/gay/pizza/pork/idea/PorkSymbolDeclaration.kt +++ b/support/pork-idea/src/main/kotlin/gay/pizza/pork/idea/PorkSymbolDeclaration.kt @@ -6,7 +6,6 @@ import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import com.intellij.psi.util.elementType import gay.pizza.pork.ast.NodeType -import gay.pizza.pork.parser.TokenType @Suppress("UnstableApiUsage") class PorkSymbolDeclaration(val element: PsiElement) : PsiSymbolDeclaration {