From a6f9a82e5e4521c0347891a39f0124f0fee34653 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Tue, 12 Sep 2023 02:03:41 -0400 Subject: [PATCH] language: none support --- ast/src/main/ast/pork.yml | 3 +++ ast/src/main/graph/types.dot | 2 ++ .../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 + .../kotlin/gay/pizza/pork/ast/NoneLiteral.kt | 22 +++++++++++++++++++ .../pizza/pork/evaluator/EvaluationVisitor.kt | 2 ++ .../gay/pizza/pork/ffi/JnaNativeProvider.kt | 19 +++++++++++----- .../kotlin/gay/pizza/pork/parser/Parser.kt | 5 +++++ .../kotlin/gay/pizza/pork/parser/Printer.kt | 4 ++++ .../kotlin/gay/pizza/pork/parser/TokenType.kt | 3 ++- 12 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 ast/src/main/kotlin/gay/pizza/pork/ast/NoneLiteral.kt diff --git a/ast/src/main/ast/pork.yml b/ast/src/main/ast/pork.yml index 8933d21..58f2acf 100644 --- a/ast/src/main/ast/pork.yml +++ b/ast/src/main/ast/pork.yml @@ -276,6 +276,9 @@ types: Continue: parent: Expression values: [] + NoneLiteral: + parent: Expression + values: [] Native: parent: Node values: diff --git a/ast/src/main/graph/types.dot b/ast/src/main/graph/types.dot index d56d0eb..5687cb7 100644 --- a/ast/src/main/graph/types.dot +++ b/ast/src/main/graph/types.dot @@ -34,6 +34,7 @@ digraph A { type_ForIn [shape=box,label="ForIn"] type_Break [shape=box,label="Break"] type_Continue [shape=box,label="Continue"] + type_NoneLiteral [shape=box,label="NoneLiteral"] type_Native [shape=box,label="Native"] type_Node -> type_Expression type_Node -> type_Symbol @@ -62,6 +63,7 @@ digraph A { type_Expression -> type_ForIn type_Expression -> type_Break type_Expression -> type_Continue + type_Expression -> type_NoneLiteral type_Definition -> type_FunctionDefinition type_Definition -> type_LetDefinition type_Declaration -> type_ImportDeclaration 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 e244746..7c0d9aa 100644 --- a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeCoalescer.kt +++ b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeCoalescer.kt @@ -56,6 +56,9 @@ class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor { override fun visitNative(node: Native): Unit = handle(node) + override fun visitNoneLiteral(node: NoneLiteral): Unit = + handle(node) + override fun visitParentheses(node: Parentheses): 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 d5ca830..ba5497f 100644 --- a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeType.kt +++ b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeType.kt @@ -24,6 +24,7 @@ enum class NodeType(val parent: NodeType? = null) { ListLiteral(Expression), LongLiteral(Expression), Native(Node), + NoneLiteral(Expression), Parentheses(Expression), PrefixOperation(Expression), SetAssignment(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 dd04374..0298337 100644 --- a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitor.kt +++ b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitor.kt @@ -38,6 +38,8 @@ interface NodeVisitor { fun visitNative(node: Native): T + fun visitNoneLiteral(node: NoneLiteral): T + fun visitParentheses(node: Parentheses): T fun visitPrefixOperation(node: PrefixOperation): 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 818bb66..295f2cd 100644 --- a/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitorExtensions.kt +++ b/ast/src/main/kotlin/gay/pizza/pork/ast/NodeVisitorExtensions.kt @@ -29,6 +29,7 @@ fun NodeVisitor.visit(node: Node): T = is ForIn -> visitForIn(node) is Break -> visitBreak(node) is Continue -> visitContinue(node) + is NoneLiteral -> visitNoneLiteral(node) is Native -> visitNative(node) } diff --git a/ast/src/main/kotlin/gay/pizza/pork/ast/NoneLiteral.kt b/ast/src/main/kotlin/gay/pizza/pork/ast/NoneLiteral.kt new file mode 100644 index 0000000..06357d3 --- /dev/null +++ b/ast/src/main/kotlin/gay/pizza/pork/ast/NoneLiteral.kt @@ -0,0 +1,22 @@ +// GENERATED CODE FROM PORK AST CODEGEN +package gay.pizza.pork.ast + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +@SerialName("noneLiteral") +class NoneLiteral : Expression() { + override val type: NodeType = NodeType.NoneLiteral + + override fun visit(visitor: NodeVisitor): T = + visitor.visitNoneLiteral(this) + + override fun equals(other: Any?): Boolean { + if (other !is NoneLiteral) return false + return true + } + + override fun hashCode(): Int = + 31 * type.hashCode() +} 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 aacabb6..408a057 100644 --- a/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/EvaluationVisitor.kt +++ b/evaluator/src/main/kotlin/gay/pizza/pork/evaluator/EvaluationVisitor.kt @@ -374,6 +374,8 @@ class EvaluationVisitor(root: Scope) : NodeVisitor { topLevelUsedError("Native", "FunctionContext") } + override fun visitNoneLiteral(node: NoneLiteral): Any = None + override fun visitContinue(node: Continue): Any = ContinueMarker private inline fun scoped(block: () -> T): T { diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/JnaNativeProvider.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/JnaNativeProvider.kt index 3e5d82a..7953c4f 100644 --- a/ffi/src/main/kotlin/gay/pizza/pork/ffi/JnaNativeProvider.kt +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/JnaNativeProvider.kt @@ -1,15 +1,18 @@ package gay.pizza.pork.ffi import com.sun.jna.Function +import com.sun.jna.NativeLibrary import com.sun.jna.Pointer import gay.pizza.pork.ast.ArgumentSpec import gay.pizza.pork.evaluator.CallableFunction import gay.pizza.pork.evaluator.NativeProvider +import gay.pizza.pork.evaluator.None class JnaNativeProvider : NativeProvider { override fun provideNativeFunction(definition: String, arguments: List): CallableFunction { val functionDefinition = FfiFunctionDefinition.parse(definition) - val function = Function.getFunction(functionDefinition.library, functionDefinition.function) + val library = NativeLibrary.getInstance(functionDefinition.library) + val function = library.getFunction(functionDefinition.function) ?: throw RuntimeException("Failed to find function ${functionDefinition.function} in library ${functionDefinition.library}") return CallableFunction { functionArgs -> val ffiArgs = mutableListOf() @@ -38,7 +41,7 @@ class JnaNativeProvider : NativeProvider { "void" -> function.invokeVoid(values) "char*" -> function.invokeString(values, false) else -> throw RuntimeException("Unsupported ffi return type: $type") - } + } ?: None private fun rewriteType(type: String): String = when (type) { "size_t" -> "long" @@ -55,7 +58,13 @@ class JnaNativeProvider : NativeProvider { "double" -> numberConvert(type, value) { toDouble() } "float" -> numberConvert(type, value) { toFloat() } "char*" -> notNullConvert(type, value) { toString() } - "void*" -> nullableConvert(value) { this as Pointer } + "void*" -> nullableConvert(value) { + if (value is Long) { + Pointer(value) + } else { + value as Pointer + } + } else -> throw RuntimeException("Unsupported ffi type: $type") } @@ -67,14 +76,14 @@ class JnaNativeProvider : NativeProvider { } private fun nullableConvert(value: Any?, into: Any.() -> T): T? { - if (value == null) { + if (value == null || value == None) { return null } return into(value) } private fun numberConvert(type: String, value: Any?, into: Number.() -> T): T { - if (value == null) { + if (value == null || value == None) { throw RuntimeException("Null values cannot be used for converting to numeric type $type") } 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 88e9be5..b0e3870 100644 --- a/parser/src/main/kotlin/gay/pizza/pork/parser/Parser.kt +++ b/parser/src/main/kotlin/gay/pizza/pork/parser/Parser.kt @@ -192,6 +192,11 @@ class Parser(source: PeekableSource, val attribution: NodeAttribution) { Continue() } + TokenType.None -> { + expect(TokenType.None) + NoneLiteral() + } + else -> { throw ParseError( "Failed to parse token: ${token.type} '${token.text}' as" + 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 b7fd6d5..400f7b3 100644 --- a/parser/src/main/kotlin/gay/pizza/pork/parser/Printer.kt +++ b/parser/src/main/kotlin/gay/pizza/pork/parser/Printer.kt @@ -81,6 +81,10 @@ class Printer(buffer: StringBuilder) : NodeVisitor { visit(node.definition) } + override fun visitNoneLiteral(node: NoneLiteral) { + append("none") + } + override fun visitSymbol(node: Symbol) { append(node.id) } diff --git a/parser/src/main/kotlin/gay/pizza/pork/parser/TokenType.kt b/parser/src/main/kotlin/gay/pizza/pork/parser/TokenType.kt index b4ab0fa..ba26b33 100644 --- a/parser/src/main/kotlin/gay/pizza/pork/parser/TokenType.kt +++ b/parser/src/main/kotlin/gay/pizza/pork/parser/TokenType.kt @@ -14,7 +14,8 @@ enum class TokenType(vararg properties: TokenTypeProperty) { StringLiteral(StringLiteralFamily), Equality(OperatorFamily), Inequality(ManyChars("!="), OperatorFamily), - ExclaimationPoint(SingleChar('!'), Promotion('=', Inequality)), + ExclamationPoint(SingleChar('!'), Promotion('=', Inequality)), + None(ManyChars("None"), KeywordFamily), Equals(SingleChar('='), Promotion('=', Equality)), PlusPlus(ManyChars("++"), OperatorFamily), MinusMinus(ManyChars("--"), OperatorFamily),