implement basic type annotations (not yet used or declarable)

This commit is contained in:
Alex Zenla 2025-07-20 00:52:24 -07:00
parent a48fac4581
commit 5ac70d800e
No known key found for this signature in database
GPG Key ID: 067B238899B51269
25 changed files with 161 additions and 28 deletions

View File

@ -18,6 +18,11 @@ types:
- name: modifiers - name: modifiers
type: DefinitionModifiers type: DefinitionModifiers
required: true required: true
TypeSpec:
parent: Node
values:
- name: symbol
type: Symbol
DefinitionModifiers: DefinitionModifiers:
values: values:
- name: export - name: export
@ -42,6 +47,8 @@ types:
type: Symbol type: Symbol
- name: value - name: value
type: Expression type: Expression
- name: typeSpec
type: TypeSpec?
VarAssignment: VarAssignment:
parent: Expression parent: Expression
namedElementValue: symbol namedElementValue: symbol
@ -50,6 +57,8 @@ types:
type: Symbol type: Symbol
- name: value - name: value
type: Expression type: Expression
- name: typeSpec
type: TypeSpec?
SetAssignment: SetAssignment:
parent: Expression parent: Expression
values: values:
@ -142,6 +151,8 @@ types:
values: values:
- name: symbol - name: symbol
type: Symbol type: Symbol
- name: typeSpec
type: TypeSpec?
- name: multiple - name: multiple
type: Boolean type: Boolean
defaultValue: "false" defaultValue: "false"
@ -155,6 +166,8 @@ types:
type: Symbol type: Symbol
- name: arguments - name: arguments
type: List<ArgumentSpec> type: List<ArgumentSpec>
- name: returnType
type: TypeSpec?
- name: block - name: block
type: Block? type: Block?
- name: nativeFunctionDescriptor - name: nativeFunctionDescriptor
@ -167,6 +180,8 @@ types:
type: DefinitionModifiers type: DefinitionModifiers
- name: symbol - name: symbol
type: Symbol type: Symbol
- name: typeSpec
type: TypeSpec?
- name: value - name: value
type: Expression type: Expression
If: If:

View File

@ -4,6 +4,7 @@ digraph A {
type_Symbol [shape=box,label="Symbol"] type_Symbol [shape=box,label="Symbol"]
type_Declaration [shape=box,label="Declaration"] type_Declaration [shape=box,label="Declaration"]
type_Definition [shape=box,label="Definition"] type_Definition [shape=box,label="Definition"]
type_TypeSpec [shape=box,label="TypeSpec"]
type_DefinitionModifiers [shape=box,label="DefinitionModifiers"] type_DefinitionModifiers [shape=box,label="DefinitionModifiers"]
type_Block [shape=box,label="Block"] type_Block [shape=box,label="Block"]
type_CompilationUnit [shape=box,label="CompilationUnit"] type_CompilationUnit [shape=box,label="CompilationUnit"]
@ -44,6 +45,7 @@ digraph A {
type_Node -> type_Symbol type_Node -> type_Symbol
type_Node -> type_Declaration type_Node -> type_Declaration
type_Node -> type_Definition type_Node -> type_Definition
type_Node -> type_TypeSpec
type_Node -> type_Block type_Node -> type_Block
type_Node -> type_CompilationUnit type_Node -> type_CompilationUnit
type_Node -> type_ArgumentSpec type_Node -> type_ArgumentSpec
@ -78,13 +80,16 @@ digraph A {
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]
type_TypeSpec -> type_Symbol [style=dotted]
type_Block -> type_Expression [style=dotted] type_Block -> type_Expression [style=dotted]
type_CompilationUnit -> type_Declaration [style=dotted] type_CompilationUnit -> type_Declaration [style=dotted]
type_CompilationUnit -> type_Definition [style=dotted] type_CompilationUnit -> type_Definition [style=dotted]
type_LetAssignment -> type_Symbol [style=dotted] type_LetAssignment -> type_Symbol [style=dotted]
type_LetAssignment -> type_Expression [style=dotted] type_LetAssignment -> type_Expression [style=dotted]
type_LetAssignment -> type_TypeSpec [style=dotted]
type_VarAssignment -> type_Symbol [style=dotted] type_VarAssignment -> type_Symbol [style=dotted]
type_VarAssignment -> type_Expression [style=dotted] type_VarAssignment -> type_Expression [style=dotted]
type_VarAssignment -> type_TypeSpec [style=dotted]
type_SetAssignment -> type_Symbol [style=dotted] type_SetAssignment -> type_Symbol [style=dotted]
type_SetAssignment -> type_Expression [style=dotted] type_SetAssignment -> type_Expression [style=dotted]
type_InfixOperation -> type_Expression [style=dotted] type_InfixOperation -> type_Expression [style=dotted]
@ -92,13 +97,16 @@ digraph A {
type_FunctionCall -> type_Symbol [style=dotted] type_FunctionCall -> type_Symbol [style=dotted]
type_FunctionCall -> type_Expression [style=dotted] type_FunctionCall -> type_Expression [style=dotted]
type_ArgumentSpec -> type_Symbol [style=dotted] type_ArgumentSpec -> type_Symbol [style=dotted]
type_ArgumentSpec -> type_TypeSpec [style=dotted]
type_FunctionDefinition -> type_DefinitionModifiers [style=dotted] type_FunctionDefinition -> type_DefinitionModifiers [style=dotted]
type_FunctionDefinition -> type_Symbol [style=dotted] type_FunctionDefinition -> type_Symbol [style=dotted]
type_FunctionDefinition -> type_ArgumentSpec [style=dotted] type_FunctionDefinition -> type_ArgumentSpec [style=dotted]
type_FunctionDefinition -> type_TypeSpec [style=dotted]
type_FunctionDefinition -> type_Block [style=dotted] type_FunctionDefinition -> type_Block [style=dotted]
type_FunctionDefinition -> type_NativeFunctionDescriptor [style=dotted] type_FunctionDefinition -> type_NativeFunctionDescriptor [style=dotted]
type_LetDefinition -> type_DefinitionModifiers [style=dotted] type_LetDefinition -> type_DefinitionModifiers [style=dotted]
type_LetDefinition -> type_Symbol [style=dotted] type_LetDefinition -> type_Symbol [style=dotted]
type_LetDefinition -> type_TypeSpec [style=dotted]
type_LetDefinition -> type_Expression [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]

View File

@ -9,6 +9,9 @@ abstract class FunctionLevelVisitor<T> : NodeVisitor<T> {
override fun visitSymbol(node: Symbol): T = override fun visitSymbol(node: Symbol): T =
throw RuntimeException("Visiting Symbol is not supported.") throw RuntimeException("Visiting Symbol is not supported.")
override fun visitTypeSpec(node: TypeSpec): T =
throw RuntimeException("Visiting TypeSpec is not supported.")
override fun visitLetDefinition(node: LetDefinition): T { override fun visitLetDefinition(node: LetDefinition): T {
topLevelUsedError("LetDefinition") topLevelUsedError("LetDefinition")
} }

View File

@ -6,22 +6,23 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName("argumentSpec") @SerialName("argumentSpec")
class ArgumentSpec(val symbol: Symbol, val multiple: Boolean = false) : Node() { class ArgumentSpec(val symbol: Symbol, val typeSpec: TypeSpec?, val multiple: Boolean = false) : Node() {
override val type: NodeType = NodeType.ArgumentSpec override val type: NodeType = NodeType.ArgumentSpec
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> = override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
visitor.visitNodes(symbol) visitor.visitNodes(symbol, typeSpec)
override fun <T> visit(visitor: NodeVisitor<T>): T = override fun <T> visit(visitor: NodeVisitor<T>): T =
visitor.visitArgumentSpec(this) visitor.visitArgumentSpec(this)
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is ArgumentSpec) return false if (other !is ArgumentSpec) return false
return other.symbol == symbol && other.multiple == multiple return other.symbol == symbol && other.typeSpec == typeSpec && other.multiple == multiple
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = symbol.hashCode() var result = symbol.hashCode()
result = 31 * result + typeSpec.hashCode()
result = 31 * result + multiple.hashCode() result = 31 * result + multiple.hashCode()
result = 31 * result + type.hashCode() result = 31 * result + type.hashCode()
return result return result

View File

@ -6,24 +6,25 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName("functionDefinition") @SerialName("functionDefinition")
class FunctionDefinition(override val modifiers: DefinitionModifiers, override val symbol: Symbol, val arguments: List<ArgumentSpec>, val block: Block?, val nativeFunctionDescriptor: NativeFunctionDescriptor?) : Definition() { class FunctionDefinition(override val modifiers: DefinitionModifiers, override val symbol: Symbol, val arguments: List<ArgumentSpec>, val returnType: TypeSpec?, val block: Block?, val nativeFunctionDescriptor: NativeFunctionDescriptor?) : Definition() {
override val type: NodeType = NodeType.FunctionDefinition override val type: NodeType = NodeType.FunctionDefinition
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> = override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
visitor.visitAll(listOf(symbol), arguments, listOf(block), listOf(nativeFunctionDescriptor)) visitor.visitAll(listOf(symbol), arguments, listOf(returnType), listOf(block), listOf(nativeFunctionDescriptor))
override fun <T> visit(visitor: NodeVisitor<T>): T = override fun <T> visit(visitor: NodeVisitor<T>): T =
visitor.visitFunctionDefinition(this) visitor.visitFunctionDefinition(this)
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is FunctionDefinition) return false if (other !is FunctionDefinition) return false
return other.modifiers == modifiers && other.symbol == symbol && other.arguments == arguments && other.block == block && other.nativeFunctionDescriptor == nativeFunctionDescriptor return other.modifiers == modifiers && other.symbol == symbol && other.arguments == arguments && other.returnType == returnType && other.block == block && other.nativeFunctionDescriptor == nativeFunctionDescriptor
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = modifiers.hashCode() var result = modifiers.hashCode()
result = 31 * result + symbol.hashCode() result = 31 * result + symbol.hashCode()
result = 31 * result + arguments.hashCode() result = 31 * result + arguments.hashCode()
result = 31 * result + returnType.hashCode()
result = 31 * result + block.hashCode() result = 31 * result + block.hashCode()
result = 31 * result + nativeFunctionDescriptor.hashCode() result = 31 * result + nativeFunctionDescriptor.hashCode()
result = 31 * result + type.hashCode() result = 31 * result + type.hashCode()

View File

@ -6,23 +6,24 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName("letAssignment") @SerialName("letAssignment")
class LetAssignment(val symbol: Symbol, val value: Expression) : Expression() { class LetAssignment(val symbol: Symbol, val value: Expression, val typeSpec: TypeSpec?) : Expression() {
override val type: NodeType = NodeType.LetAssignment override val type: NodeType = NodeType.LetAssignment
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> = override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
visitor.visitNodes(symbol, value) visitor.visitNodes(symbol, value, typeSpec)
override fun <T> visit(visitor: NodeVisitor<T>): T = override fun <T> visit(visitor: NodeVisitor<T>): T =
visitor.visitLetAssignment(this) visitor.visitLetAssignment(this)
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is LetAssignment) return false if (other !is LetAssignment) return false
return other.symbol == symbol && other.value == value return other.symbol == symbol && other.value == value && other.typeSpec == typeSpec
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = symbol.hashCode() var result = symbol.hashCode()
result = 31 * result + value.hashCode() result = 31 * result + value.hashCode()
result = 31 * result + typeSpec.hashCode()
result = 31 * result + type.hashCode() result = 31 * result + type.hashCode()
return result return result
} }

View File

@ -6,23 +6,24 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName("letDefinition") @SerialName("letDefinition")
class LetDefinition(override val modifiers: DefinitionModifiers, override val symbol: Symbol, val value: Expression) : Definition() { class LetDefinition(override val modifiers: DefinitionModifiers, override val symbol: Symbol, val typeSpec: TypeSpec?, val value: Expression) : Definition() {
override val type: NodeType = NodeType.LetDefinition override val type: NodeType = NodeType.LetDefinition
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> = override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
visitor.visitNodes(symbol, value) visitor.visitNodes(symbol, typeSpec, value)
override fun <T> visit(visitor: NodeVisitor<T>): T = override fun <T> visit(visitor: NodeVisitor<T>): T =
visitor.visitLetDefinition(this) visitor.visitLetDefinition(this)
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is LetDefinition) return false if (other !is LetDefinition) return false
return other.modifiers == modifiers && other.symbol == symbol && other.value == value return other.modifiers == modifiers && other.symbol == symbol && other.typeSpec == typeSpec && other.value == value
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = modifiers.hashCode() var result = modifiers.hashCode()
result = 31 * result + symbol.hashCode() result = 31 * result + symbol.hashCode()
result = 31 * result + typeSpec.hashCode()
result = 31 * result + value.hashCode() result = 31 * result + value.hashCode()
result = 31 * result + type.hashCode() result = 31 * result + type.hashCode()
return result return result

View File

@ -95,6 +95,9 @@ class NodeCoalescer(val followChildren: Boolean = true, val handler: (Node) -> U
override fun visitSymbolReference(node: SymbolReference): Unit = override fun visitSymbolReference(node: SymbolReference): Unit =
handle(node) handle(node)
override fun visitTypeSpec(node: TypeSpec): Unit =
handle(node)
override fun visitVarAssignment(node: VarAssignment): Unit = override fun visitVarAssignment(node: VarAssignment): Unit =
handle(node) handle(node)

View File

@ -70,6 +70,8 @@ interface NodeParser {
fun parseSymbolReference(): SymbolReference fun parseSymbolReference(): SymbolReference
fun parseTypeSpec(): TypeSpec
fun parseVarAssignment(): VarAssignment fun parseVarAssignment(): VarAssignment
fun parseWhile(): While fun parseWhile(): While

View File

@ -7,6 +7,7 @@ fun NodeParser.parse(type: NodeType): Node =
NodeType.Symbol -> parseSymbol() NodeType.Symbol -> parseSymbol()
NodeType.Declaration -> parseDeclaration() NodeType.Declaration -> parseDeclaration()
NodeType.Definition -> parseDefinition() NodeType.Definition -> parseDefinition()
NodeType.TypeSpec -> parseTypeSpec()
NodeType.Block -> parseBlock() NodeType.Block -> parseBlock()
NodeType.CompilationUnit -> parseCompilationUnit() NodeType.CompilationUnit -> parseCompilationUnit()
NodeType.LetAssignment -> parseLetAssignment() NodeType.LetAssignment -> parseLetAssignment()

View File

@ -37,6 +37,7 @@ enum class NodeType(val parent: NodeType? = null) {
SuffixOperation(Expression), SuffixOperation(Expression),
Symbol(Node), Symbol(Node),
SymbolReference(Expression), SymbolReference(Expression),
TypeSpec(Node),
VarAssignment(Expression), VarAssignment(Expression),
While(Expression) While(Expression)
} }

View File

@ -64,6 +64,8 @@ interface NodeVisitor<T> {
fun visitSymbolReference(node: SymbolReference): T fun visitSymbolReference(node: SymbolReference): T
fun visitTypeSpec(node: TypeSpec): T
fun visitVarAssignment(node: VarAssignment): T fun visitVarAssignment(node: VarAssignment): T
fun visitWhile(node: While): T fun visitWhile(node: While): T

View File

@ -4,6 +4,7 @@ package gay.pizza.pork.ast.gen
fun <T> NodeVisitor<T>.visit(node: Node): T = fun <T> NodeVisitor<T>.visit(node: Node): T =
when (node) { when (node) {
is Symbol -> visitSymbol(node) is Symbol -> visitSymbol(node)
is TypeSpec -> visitTypeSpec(node)
is Block -> visitBlock(node) is Block -> visitBlock(node)
is CompilationUnit -> visitCompilationUnit(node) is CompilationUnit -> visitCompilationUnit(node)
is LetAssignment -> visitLetAssignment(node) is LetAssignment -> visitLetAssignment(node)

View File

@ -0,0 +1,28 @@
// GENERATED CODE FROM PORK AST CODEGEN
package gay.pizza.pork.ast.gen
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
@SerialName("typeSpec")
class TypeSpec(val symbol: Symbol) : Node() {
override val type: NodeType = NodeType.TypeSpec
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
visitor.visitNodes(symbol)
override fun <T> visit(visitor: NodeVisitor<T>): T =
visitor.visitTypeSpec(this)
override fun equals(other: Any?): Boolean {
if (other !is TypeSpec) return false
return other.symbol == symbol
}
override fun hashCode(): Int {
var result = symbol.hashCode()
result = 31 * result + type.hashCode()
return result
}
}

View File

@ -6,23 +6,24 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName("varAssignment") @SerialName("varAssignment")
class VarAssignment(val symbol: Symbol, val value: Expression) : Expression() { class VarAssignment(val symbol: Symbol, val value: Expression, val typeSpec: TypeSpec?) : Expression() {
override val type: NodeType = NodeType.VarAssignment override val type: NodeType = NodeType.VarAssignment
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> = override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
visitor.visitNodes(symbol, value) visitor.visitNodes(symbol, value, typeSpec)
override fun <T> visit(visitor: NodeVisitor<T>): T = override fun <T> visit(visitor: NodeVisitor<T>): T =
visitor.visitVarAssignment(this) visitor.visitVarAssignment(this)
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is VarAssignment) return false if (other !is VarAssignment) return false
return other.symbol == symbol && other.value == value return other.symbol == symbol && other.value == value && other.typeSpec == typeSpec
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = symbol.hashCode() var result = symbol.hashCode()
result = 31 * result + value.hashCode() result = 31 * result + value.hashCode()
result = 31 * result + typeSpec.hashCode()
result = 31 * result + type.hashCode() result = 31 * result + type.hashCode()
return result return result
} }

View File

@ -54,8 +54,6 @@ class EvaluationVisitor(root: Scope, val stack: CallStack) : FunctionLevelVisito
override fun visitLongLiteral(node: LongLiteral): Any = node.value override fun visitLongLiteral(node: LongLiteral): Any = node.value
override fun visitSymbol(node: Symbol): Any = None
override fun visitFunctionCall(node: FunctionCall): Any { override fun visitFunctionCall(node: FunctionCall): Any {
val arguments = node.arguments.map { it.visit(this) } val arguments = node.arguments.map { it.visit(this) }
val functionValue = currentScope.value(node.symbol.id) as CallableFunction val functionValue = currentScope.value(node.symbol.id) as CallableFunction

View File

@ -1,5 +1,5 @@
/* fibonacci sequence */ /* fibonacci sequence */
func fib(n) { func fib(n: int32): int32 {
if n < 2 { if n < 2 {
return n return n
} else { } else {
@ -8,6 +8,6 @@ func fib(n) {
} }
export func main() { export func main() {
let result = fib(28) let result: int32 = fib(28)
println(result) println(result)
} }

View File

@ -118,7 +118,7 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider {
val buffer = HeapInvocationBuffer(context) val buffer = HeapInvocationBuffer(context)
val useFunctionArguments = functionArgumentSpecs ?: functionArguments.map { val useFunctionArguments = functionArgumentSpecs ?: functionArguments.map {
ArgumentSpec(symbol = Symbol(""), multiple = false) ArgumentSpec(symbol = Symbol(""), typeSpec = null, multiple = false)
} }
for ((index, spec) in useFunctionArguments.withIndex()) { for ((index, spec) in useFunctionArguments.withIndex()) {

View File

@ -147,11 +147,13 @@ class JavaAutogen(val javaClass: Class<*>) {
arguments = parameterNames.map { arguments = parameterNames.map {
ArgumentSpec( ArgumentSpec(
symbol = Symbol(it), symbol = Symbol(it),
multiple = false multiple = false,
typeSpec = null,
) )
}, },
nativeFunctionDescriptor = asNative(functionDefinition), nativeFunctionDescriptor = asNative(functionDefinition),
block = null block = null,
returnType = null,
) )
private fun asNative(functionDefinition: JavaFunctionDefinition): NativeFunctionDescriptor = private fun asNative(functionDefinition: JavaFunctionDefinition): NativeFunctionDescriptor =

View File

@ -119,6 +119,10 @@ class ExternalSymbolUsageAnalyzer : FunctionLevelVisitor<Unit>() {
checkAndContribute(node.symbol) checkAndContribute(node.symbol)
} }
override fun visitTypeSpec(node: TypeSpec) {
checkAndContribute(node.symbol)
}
override fun visitVarAssignment(node: VarAssignment) { override fun visitVarAssignment(node: VarAssignment) {
internalSymbols.last().add(node.symbol) internalSymbols.last().add(node.symbol)
node.value.visit(this) node.value.visit(this)

View File

@ -8,7 +8,11 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
ParserBase(source, attribution) { ParserBase(source, attribution) {
override fun parseArgumentSpec(): ArgumentSpec = produce(NodeType.ArgumentSpec) { override fun parseArgumentSpec(): ArgumentSpec = produce(NodeType.ArgumentSpec) {
val symbol = parseSymbol() val symbol = parseSymbol()
ArgumentSpec(symbol, next(TokenType.DotDotDot)) var typeSpec: TypeSpec? = null
if (next(TokenType.Colon)) {
typeSpec = parseTypeSpec()
}
ArgumentSpec(symbol, typeSpec = typeSpec, next(TokenType.DotDotDot))
} }
override fun parseBlock(): Block = expect(NodeType.Block, TokenType.LeftCurly) { override fun parseBlock(): Block = expect(NodeType.Block, TokenType.LeftCurly) {
@ -213,7 +217,10 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
parseArgumentSpec() parseArgumentSpec()
} }
expect(TokenType.RightParentheses) expect(TokenType.RightParentheses)
var returnType: TypeSpec? = null
if (next(TokenType.Colon)) {
returnType = parseTypeSpec()
}
var native: NativeFunctionDescriptor? = null var native: NativeFunctionDescriptor? = null
var block: Block? = null var block: Block? = null
if (peek(TokenType.Native)) { if (peek(TokenType.Native)) {
@ -221,7 +228,7 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
} else { } else {
block = parseBlock() block = parseBlock()
} }
FunctionDefinition(modifiers, name, arguments, block, native) FunctionDefinition(modifiers = modifiers, symbol = name, arguments = arguments, returnType = returnType, block = block, nativeFunctionDescriptor = native)
} }
override fun parseIf(): If = expect(NodeType.If, TokenType.If) { override fun parseIf(): If = expect(NodeType.If, TokenType.If) {
@ -280,18 +287,26 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
override fun parseLetAssignment(): LetAssignment = expect(NodeType.LetAssignment, TokenType.Let) { override fun parseLetAssignment(): LetAssignment = expect(NodeType.LetAssignment, TokenType.Let) {
val symbol = parseSymbol() val symbol = parseSymbol()
var typeSpec: TypeSpec? = null
if (next(TokenType.Colon)) {
typeSpec = parseTypeSpec()
}
expect(TokenType.Equals) expect(TokenType.Equals)
val value = parseExpression() val value = parseExpression()
LetAssignment(symbol, value) LetAssignment(symbol = symbol, typeSpec = typeSpec, value = value)
} }
override fun parseLetDefinition(): LetDefinition = produce(NodeType.LetDefinition) { override fun parseLetDefinition(): LetDefinition = produce(NodeType.LetDefinition) {
val definitionModifiers = parseDefinitionModifiers() val definitionModifiers = parseDefinitionModifiers()
expect(TokenType.Let) expect(TokenType.Let)
val name = parseSymbol() val name = parseSymbol()
var typeSpec: TypeSpec? = null
if (next(TokenType.Colon)) {
typeSpec = parseTypeSpec()
}
expect(TokenType.Equals) expect(TokenType.Equals)
val value = parseExpression() val value = parseExpression()
LetDefinition(definitionModifiers, name, value) LetDefinition(modifiers = definitionModifiers, symbol = name, typeSpec = typeSpec, value = value)
} }
override fun parseListLiteral(): ListLiteral = expect(NodeType.ListLiteral, TokenType.LeftBracket) { override fun parseListLiteral(): ListLiteral = expect(NodeType.ListLiteral, TokenType.LeftBracket) {
@ -375,11 +390,19 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
SymbolReference(parseSymbol()) SymbolReference(parseSymbol())
} }
override fun parseTypeSpec(): TypeSpec = produce(NodeType.TypeSpec) {
TypeSpec(parseSymbol())
}
override fun parseVarAssignment(): VarAssignment = expect(NodeType.VarAssignment, TokenType.Var) { override fun parseVarAssignment(): VarAssignment = expect(NodeType.VarAssignment, TokenType.Var) {
val symbol = parseSymbol() val symbol = parseSymbol()
var typeSpec: TypeSpec? = null
if (next(TokenType.Colon)) {
typeSpec = parseTypeSpec()
}
expect(TokenType.Equals) expect(TokenType.Equals)
val value = parseExpression() val value = parseExpression()
VarAssignment(symbol, value) VarAssignment(symbol = symbol, typeSpec = typeSpec, value = value)
} }
override fun parseWhile(): While = expect(NodeType.While, TokenType.While) { override fun parseWhile(): While = expect(NodeType.While, TokenType.While) {

View File

@ -113,6 +113,10 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
override fun visitLetAssignment(node: LetAssignment) { override fun visitLetAssignment(node: LetAssignment) {
append("let ") append("let ")
visit(node.symbol) visit(node.symbol)
if (node.typeSpec != null) {
append(": ")
visit(node.typeSpec!!)
}
append(" = ") append(" = ")
visit(node.value) visit(node.value)
} }
@ -121,6 +125,10 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
visitDefinitionModifiers(node.modifiers) visitDefinitionModifiers(node.modifiers)
append("let ") append("let ")
visit(node.symbol) visit(node.symbol)
if (node.typeSpec != null) {
append(": ")
visit(node.typeSpec!!)
}
append(" = ") append(" = ")
visit(node.value) visit(node.value)
} }
@ -129,9 +137,17 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
visit(node.symbol) visit(node.symbol)
} }
override fun visitTypeSpec(node: TypeSpec) {
visit(node.symbol)
}
override fun visitVarAssignment(node: VarAssignment) { override fun visitVarAssignment(node: VarAssignment) {
append("var ") append("var ")
visit(node.symbol) visit(node.symbol)
if (node.typeSpec != null) {
append(": ")
visit(node.typeSpec!!)
}
append(" = ") append(" = ")
visit(node.value) visit(node.value)
} }
@ -209,6 +225,10 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
} }
} }
append(") ") append(") ")
if (node.returnType != null) {
append(": ")
visit(node.returnType!!)
}
if (node.block != null) { if (node.block != null) {
visit(node.block!!) visit(node.block!!)
} }

View File

@ -11,6 +11,7 @@ object PorkElementFactory {
fun create(node: ASTNode): PsiElement = fun create(node: ASTNode): PsiElement =
when (PorkElementTypes.nodeTypeFor(node.elementType)) { when (PorkElementTypes.nodeTypeFor(node.elementType)) {
NodeType.Symbol -> SymbolElement(node) NodeType.Symbol -> SymbolElement(node)
NodeType.TypeSpec -> TypeSpecElement(node)
NodeType.Block -> BlockElement(node) NodeType.Block -> BlockElement(node)
NodeType.CompilationUnit -> CompilationUnitElement(node) NodeType.CompilationUnit -> CompilationUnitElement(node)
NodeType.LetAssignment -> LetAssignmentElement(node) NodeType.LetAssignment -> LetAssignmentElement(node)

View File

@ -0,0 +1,15 @@
// GENERATED CODE FROM PORK AST CODEGEN
package gay.pizza.pork.idea.psi.gen
import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation
import gay.pizza.pork.idea.psi.PorkElementHelpers
import javax.swing.Icon
class TypeSpecElement(node: ASTNode) : PorkElement(node) {
override fun getIcon(flags: Int): Icon? =
PorkElementHelpers.iconOf(this)
override fun getPresentation(): ItemPresentation? =
PorkElementHelpers.presentationOf(this)
}

View File

@ -50,6 +50,7 @@ enum class TokenType(vararg val properties: TokenTypeProperty) {
Mod(ManyChars("mod"), KeywordFamily), Mod(ManyChars("mod"), KeywordFamily),
Rem(ManyChars("rem"), KeywordFamily), Rem(ManyChars("rem"), KeywordFamily),
Comma(SingleChar(',')), Comma(SingleChar(',')),
Colon(SingleChar(':')),
DotDotDot(ManyChars("...")), DotDotDot(ManyChars("...")),
DotDot(ManyChars(".."), Promotion('.', DotDotDot)), DotDot(ManyChars(".."), Promotion('.', DotDotDot)),
Dot(SingleChar('.'), Promotion('.', DotDot)), Dot(SingleChar('.'), Promotion('.', DotDot)),