implement support for setting indexed values

This commit is contained in:
Alex Zenla 2025-07-26 17:01:24 -07:00
parent 48e19a8068
commit 3dcac2f9e6
No known key found for this signature in database
GPG Key ID: 067B238899B51269
26 changed files with 201 additions and 44 deletions

View File

@ -59,13 +59,22 @@ types:
type: Expression type: Expression
- name: typeSpec - name: typeSpec
type: TypeSpec? type: TypeSpec?
SetAssignment: SymbolSetAssignment:
parent: Expression parent: Expression
values: values:
- name: symbol - name: symbol
type: Symbol type: Symbol
- name: value - name: value
type: Expression type: Expression
IndexedSetAssignment:
parent: Expression
values:
- name: target
type: Expression
- name: index
type: Expression
- name: value
type: Expression
InfixOperator: InfixOperator:
values: values:
- name: token - name: token

View File

@ -10,7 +10,8 @@ digraph A {
type_CompilationUnit [shape=box,label="CompilationUnit"] type_CompilationUnit [shape=box,label="CompilationUnit"]
type_LetAssignment [shape=box,label="LetAssignment"] type_LetAssignment [shape=box,label="LetAssignment"]
type_VarAssignment [shape=box,label="VarAssignment"] type_VarAssignment [shape=box,label="VarAssignment"]
type_SetAssignment [shape=box,label="SetAssignment"] type_SymbolSetAssignment [shape=box,label="SymbolSetAssignment"]
type_IndexedSetAssignment [shape=box,label="IndexedSetAssignment"]
type_InfixOperator [shape=box,label="InfixOperator"] type_InfixOperator [shape=box,label="InfixOperator"]
type_InfixOperation [shape=box,label="InfixOperation"] type_InfixOperation [shape=box,label="InfixOperation"]
type_BooleanLiteral [shape=box,label="BooleanLiteral"] type_BooleanLiteral [shape=box,label="BooleanLiteral"]
@ -57,7 +58,8 @@ digraph A {
type_Node -> type_NativeTypeDescriptor type_Node -> type_NativeTypeDescriptor
type_Expression -> type_LetAssignment type_Expression -> type_LetAssignment
type_Expression -> type_VarAssignment type_Expression -> type_VarAssignment
type_Expression -> type_SetAssignment type_Expression -> type_SymbolSetAssignment
type_Expression -> type_IndexedSetAssignment
type_Expression -> type_InfixOperation type_Expression -> type_InfixOperation
type_Expression -> type_BooleanLiteral type_Expression -> type_BooleanLiteral
type_Expression -> type_FunctionCall type_Expression -> type_FunctionCall
@ -94,8 +96,9 @@ digraph A {
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_VarAssignment -> type_TypeSpec [style=dotted]
type_SetAssignment -> type_Symbol [style=dotted] type_SymbolSetAssignment -> type_Symbol [style=dotted]
type_SetAssignment -> type_Expression [style=dotted] type_SymbolSetAssignment -> type_Expression [style=dotted]
type_IndexedSetAssignment -> type_Expression [style=dotted]
type_InfixOperation -> type_Expression [style=dotted] type_InfixOperation -> type_Expression [style=dotted]
type_InfixOperation -> type_InfixOperator [style=dotted] type_InfixOperation -> type_InfixOperator [style=dotted]
type_FunctionCall -> type_Symbol [style=dotted] type_FunctionCall -> type_Symbol [style=dotted]

View File

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

View File

@ -47,6 +47,9 @@ class NodeCoalescer(val followChildren: Boolean = true, val handler: (Node) -> U
override fun visitIndexedBy(node: IndexedBy): Unit = override fun visitIndexedBy(node: IndexedBy): Unit =
handle(node) handle(node)
override fun visitIndexedSetAssignment(node: IndexedSetAssignment): Unit =
handle(node)
override fun visitInfixOperation(node: InfixOperation): Unit = override fun visitInfixOperation(node: InfixOperation): Unit =
handle(node) handle(node)
@ -83,9 +86,6 @@ class NodeCoalescer(val followChildren: Boolean = true, val handler: (Node) -> U
override fun visitReturn(node: Return): Unit = override fun visitReturn(node: Return): Unit =
handle(node) handle(node)
override fun visitSetAssignment(node: SetAssignment): Unit =
handle(node)
override fun visitStringLiteral(node: StringLiteral): Unit = override fun visitStringLiteral(node: StringLiteral): Unit =
handle(node) handle(node)
@ -98,6 +98,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 visitSymbolSetAssignment(node: SymbolSetAssignment): Unit =
handle(node)
override fun visitTypeDefinition(node: TypeDefinition): Unit = override fun visitTypeDefinition(node: TypeDefinition): Unit =
handle(node) handle(node)

View File

@ -38,6 +38,8 @@ interface NodeParser {
fun parseIndexedBy(): IndexedBy fun parseIndexedBy(): IndexedBy
fun parseIndexedSetAssignment(): IndexedSetAssignment
fun parseInfixOperation(): InfixOperation fun parseInfixOperation(): InfixOperation
fun parseIntegerLiteral(): IntegerLiteral fun parseIntegerLiteral(): IntegerLiteral
@ -62,8 +64,6 @@ interface NodeParser {
fun parseReturn(): Return fun parseReturn(): Return
fun parseSetAssignment(): SetAssignment
fun parseStringLiteral(): StringLiteral fun parseStringLiteral(): StringLiteral
fun parseSuffixOperation(): SuffixOperation fun parseSuffixOperation(): SuffixOperation
@ -72,6 +72,8 @@ interface NodeParser {
fun parseSymbolReference(): SymbolReference fun parseSymbolReference(): SymbolReference
fun parseSymbolSetAssignment(): SymbolSetAssignment
fun parseTypeDefinition(): TypeDefinition fun parseTypeDefinition(): TypeDefinition
fun parseTypeSpec(): TypeSpec fun parseTypeSpec(): TypeSpec

View File

@ -12,7 +12,8 @@ fun NodeParser.parse(type: NodeType): Node =
NodeType.CompilationUnit -> parseCompilationUnit() NodeType.CompilationUnit -> parseCompilationUnit()
NodeType.LetAssignment -> parseLetAssignment() NodeType.LetAssignment -> parseLetAssignment()
NodeType.VarAssignment -> parseVarAssignment() NodeType.VarAssignment -> parseVarAssignment()
NodeType.SetAssignment -> parseSetAssignment() NodeType.SymbolSetAssignment -> parseSymbolSetAssignment()
NodeType.IndexedSetAssignment -> parseIndexedSetAssignment()
NodeType.InfixOperation -> parseInfixOperation() NodeType.InfixOperation -> parseInfixOperation()
NodeType.BooleanLiteral -> parseBooleanLiteral() NodeType.BooleanLiteral -> parseBooleanLiteral()
NodeType.FunctionCall -> parseFunctionCall() NodeType.FunctionCall -> parseFunctionCall()

View File

@ -21,6 +21,7 @@ enum class NodeType(val parent: NodeType? = null) {
ImportDeclaration(Declaration), ImportDeclaration(Declaration),
ImportPath(Node), ImportPath(Node),
IndexedBy(Expression), IndexedBy(Expression),
IndexedSetAssignment(Expression),
InfixOperation(Expression), InfixOperation(Expression),
IntegerLiteral(Expression), IntegerLiteral(Expression),
LetAssignment(Expression), LetAssignment(Expression),
@ -33,11 +34,11 @@ enum class NodeType(val parent: NodeType? = null) {
Parentheses(Expression), Parentheses(Expression),
PrefixOperation(Expression), PrefixOperation(Expression),
Return(Expression), Return(Expression),
SetAssignment(Expression),
StringLiteral(Expression), StringLiteral(Expression),
SuffixOperation(Expression), SuffixOperation(Expression),
Symbol(Node), Symbol(Node),
SymbolReference(Expression), SymbolReference(Expression),
SymbolSetAssignment(Expression),
TypeDefinition(Definition), TypeDefinition(Definition),
TypeSpec(Node), TypeSpec(Node),
VarAssignment(Expression), VarAssignment(Expression),

View File

@ -32,6 +32,8 @@ interface NodeVisitor<T> {
fun visitIndexedBy(node: IndexedBy): T fun visitIndexedBy(node: IndexedBy): T
fun visitIndexedSetAssignment(node: IndexedSetAssignment): T
fun visitInfixOperation(node: InfixOperation): T fun visitInfixOperation(node: InfixOperation): T
fun visitIntegerLiteral(node: IntegerLiteral): T fun visitIntegerLiteral(node: IntegerLiteral): T
@ -56,8 +58,6 @@ interface NodeVisitor<T> {
fun visitReturn(node: Return): T fun visitReturn(node: Return): T
fun visitSetAssignment(node: SetAssignment): T
fun visitStringLiteral(node: StringLiteral): T fun visitStringLiteral(node: StringLiteral): T
fun visitSuffixOperation(node: SuffixOperation): T fun visitSuffixOperation(node: SuffixOperation): T
@ -66,6 +66,8 @@ interface NodeVisitor<T> {
fun visitSymbolReference(node: SymbolReference): T fun visitSymbolReference(node: SymbolReference): T
fun visitSymbolSetAssignment(node: SymbolSetAssignment): T
fun visitTypeDefinition(node: TypeDefinition): T fun visitTypeDefinition(node: TypeDefinition): T
fun visitTypeSpec(node: TypeSpec): T fun visitTypeSpec(node: TypeSpec): T

View File

@ -9,7 +9,8 @@ fun <T> NodeVisitor<T>.visit(node: Node): T =
is CompilationUnit -> visitCompilationUnit(node) is CompilationUnit -> visitCompilationUnit(node)
is LetAssignment -> visitLetAssignment(node) is LetAssignment -> visitLetAssignment(node)
is VarAssignment -> visitVarAssignment(node) is VarAssignment -> visitVarAssignment(node)
is SetAssignment -> visitSetAssignment(node) is SymbolSetAssignment -> visitSymbolSetAssignment(node)
is IndexedSetAssignment -> visitIndexedSetAssignment(node)
is InfixOperation -> visitInfixOperation(node) is InfixOperation -> visitInfixOperation(node)
is BooleanLiteral -> visitBooleanLiteral(node) is BooleanLiteral -> visitBooleanLiteral(node)
is FunctionCall -> visitFunctionCall(node) is FunctionCall -> visitFunctionCall(node)

View File

@ -5,18 +5,18 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
@SerialName("setAssignment") @SerialName("symbolSetAssignment")
class SetAssignment(val symbol: Symbol, val value: Expression) : Expression() { class SymbolSetAssignment(val symbol: Symbol, val value: Expression) : Expression() {
override val type: NodeType = NodeType.SetAssignment override val type: NodeType = NodeType.SymbolSetAssignment
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)
override fun <T> visit(visitor: NodeVisitor<T>): T = override fun <T> visit(visitor: NodeVisitor<T>): T =
visitor.visitSetAssignment(this) visitor.visitSymbolSetAssignment(this)
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is SetAssignment) return false if (other !is SymbolSetAssignment) return false
return other.symbol == symbol && other.value == value return other.symbol == symbol && other.value == value
} }

View File

@ -3,9 +3,12 @@ package gay.pizza.pork.bir
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
data class IrIndex(var data: IrCodeElement, var index: IrCodeElement) : IrCodeElement() { data class IrIndex(var data: IrCodeElement, var index: IrCodeElement, var value: IrCodeElement? = null) : IrCodeElement() {
override fun crawl(block: (IrElement) -> Unit) { override fun crawl(block: (IrElement) -> Unit) {
block(data) block(data)
block(index) block(index)
if (value != null) {
block(value!!)
}
} }
} }

View File

@ -40,6 +40,7 @@ enum class Opcode(val id: UByte) {
EuclideanModulo(37u), EuclideanModulo(37u),
Remainder(38u), Remainder(38u),
Index(39u), Index(39u),
IndexSet(44u),
ScopeIn(40u), ScopeIn(40u),
ScopeOut(41u), ScopeOut(41u),
ReturnAddress(42u), ReturnAddress(42u),

View File

@ -228,6 +228,12 @@ class AstIrEmitter(
index = visit(node.index) index = visit(node.index)
) )
override fun visitIndexedSetAssignment(node: IndexedSetAssignment): IrCodeElement = IrIndex(
data = visit(node.target),
index = visit(node.index),
value = visit(node.value),
)
override fun visitInfixOperation(node: InfixOperation): IrCodeElement { override fun visitInfixOperation(node: InfixOperation): IrCodeElement {
val op = when (node.op) { val op = when (node.op) {
InfixOperator.Plus -> IrInfixOp.Add InfixOperator.Plus -> IrInfixOp.Add
@ -288,7 +294,7 @@ class AstIrEmitter(
override fun visitReturn(node: Return): IrCodeElement = override fun visitReturn(node: Return): IrCodeElement =
IrReturn(from = self, value = node.value.visit(this)) IrReturn(from = self, value = node.value.visit(this))
override fun visitSetAssignment(node: SetAssignment): IrCodeElement { override fun visitSymbolSetAssignment(node: SymbolSetAssignment): IrCodeElement {
val symbol = lookupLocalVariable(node.symbol) ?: val symbol = lookupLocalVariable(node.symbol) ?:
throw CompileError("Unable to find local variable target '${node.symbol.id}'", node) throw CompileError("Unable to find local variable target '${node.symbol.id}'", node)
return IrStore(symbol, node.value.visit(this)) return IrStore(symbol, node.value.visit(this))

View File

@ -248,9 +248,16 @@ class IrStubOpEmitter(val irDefinition: IrDefinition, val code: CodeBuilder) : I
} }
override fun visitIrIndex(ir: IrIndex) { override fun visitIrIndex(ir: IrIndex) {
if (ir.value != null) {
visit(ir.value!!)
}
visit(ir.index) visit(ir.index)
visit(ir.data) visit(ir.data)
code.emit(Opcode.Index) if (ir.value != null) {
code.emit(Opcode.IndexSet)
} else {
code.emit(Opcode.Index)
}
} }
override fun visitIrListSize(ir: IrListSize) { override fun visitIrListSize(ir: IrListSize) {

View File

@ -177,7 +177,7 @@ class EvaluationVisitor(root: Scope, val stack: CallStack) : FunctionLevelVisito
return previousValue return previousValue
} }
override fun visitSetAssignment(node: SetAssignment): Any { override fun visitSymbolSetAssignment(node: SymbolSetAssignment): Any {
val value = node.value.visit(this) val value = node.value.visit(this)
currentScope.set(node.symbol.id, value) currentScope.set(node.symbol.id, value)
return value return value
@ -399,6 +399,24 @@ class EvaluationVisitor(root: Scope, val stack: CallStack) : FunctionLevelVisito
throw RuntimeException("Failed to index '${value}' by '${index}': Unsupported types used.") throw RuntimeException("Failed to index '${value}' by '${index}': Unsupported types used.")
} }
override fun visitIndexedSetAssignment(node: IndexedSetAssignment): Any {
val value = node.value.visit(this)
val index = node.index.visit(this)
val target = node.target.visit(this)
if (target is MutableList<*> && index is Number) {
@Suppress("UNCHECKED_CAST")
(target as MutableList<Any?>)[index.toInt()] = value
return None
}
if (target is Array<*> && index is Number) {
@Suppress("UNCHECKED_CAST")
(target as MutableList<Any?>)[index.toInt()] = value
return None
}
return value
}
override fun visitNoneLiteral(node: NoneLiteral): Any = None override fun visitNoneLiteral(node: NoneLiteral): Any = None
override fun visitContinue(node: Continue): Any = ContinueMarker override fun visitContinue(node: Continue): Any = ContinueMarker

View File

@ -73,8 +73,8 @@ func setCell(cells, swap, x, y, state) {
let mask = if swap { 2 } else { 1 } let mask = if swap { 2 } else { 1 }
let idx = x + y * gridWidth let idx = x + y * gridWidth
let value = cells[idx] let value = cells[idx]
if state { listSet(cells, idx, value | mask) } if state { cells[idx] = value | mask }
else { listSet(cells, idx, value & (~mask)) } else { cells[idx] = value & (~mask) }
} }
} }

View File

@ -1,4 +1,6 @@
export func main() { export func main() {
let items = [["Hello"], ["Goodbye"]] let items = [["Hello"], ["Goodbye"]]
println(items[0][0]) println(items[0][0])
items[0][0] = "Goodbye"
println(items[0][0])
} }

View File

@ -2,6 +2,7 @@ package gay.pizza.pork.frontend.scope
import gay.pizza.pork.ast.FunctionLevelVisitor import gay.pizza.pork.ast.FunctionLevelVisitor
import gay.pizza.pork.ast.gen.* import gay.pizza.pork.ast.gen.*
import gay.pizza.pork.ast.gen.visit
class ExternalSymbolUsageAnalyzer : FunctionLevelVisitor<Unit>() { class ExternalSymbolUsageAnalyzer : FunctionLevelVisitor<Unit>() {
private val symbols = mutableSetOf<Symbol>() private val symbols = mutableSetOf<Symbol>()
@ -116,8 +117,13 @@ class ExternalSymbolUsageAnalyzer : FunctionLevelVisitor<Unit>() {
node.visitChildren(this) node.visitChildren(this)
} }
override fun visitSetAssignment(node: SetAssignment) { override fun visitSymbolSetAssignment(node: SymbolSetAssignment) {
node.value.visit(this) checkAndContribute(node.symbol)
node.visitChildren(this)
}
override fun visitIndexedSetAssignment(node: IndexedSetAssignment) {
node.visitChildren(this)
} }
override fun visitStringLiteral(node: StringLiteral) { override fun visitStringLiteral(node: StringLiteral) {

View File

@ -53,16 +53,6 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
} }
} }
if (expression is SymbolReference && peek(TokenType.Equals)) {
val symbolReference = expression
expression = produce(NodeType.SetAssignment) {
attribution.adopt(expression)
expect(TokenType.Equals)
val value = parseExpression()
SetAssignment(symbolReference.symbol, value)
}
}
while (peek(TokenType.LeftBracket)) { while (peek(TokenType.LeftBracket)) {
expression = produce(NodeType.IndexedBy) { expression = produce(NodeType.IndexedBy) {
attribution.adopt(expression) attribution.adopt(expression)
@ -73,12 +63,33 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
} }
} }
if (expression is SymbolReference && peek(TokenType.Equals)) {
val symbolReference = expression
expression = produce(NodeType.SymbolSetAssignment) {
attribution.adopt(expression)
expect(TokenType.Equals)
val value = parseExpression()
SymbolSetAssignment(symbolReference.symbol, value)
}
}
if (expression is IndexedBy && peek(TokenType.Equals)) {
val indexedBy = expression
expression = produce(NodeType.IndexedSetAssignment) {
attribution.adopt(indexedBy)
expect(TokenType.Equals)
val value = parseExpression()
IndexedSetAssignment(target = indexedBy.expression, index = indexedBy.index, value = value)
}
}
return if (peek( return if (peek(
TokenType.Plus, TokenType.Minus, TokenType.Multiply, TokenType.Divide, TokenType.Ampersand, TokenType.Plus, TokenType.Minus, TokenType.Multiply, TokenType.Divide, TokenType.Ampersand,
TokenType.Pipe, TokenType.Caret, TokenType.Equality, TokenType.Inequality, TokenType.Mod, TokenType.Pipe, TokenType.Caret, TokenType.Equality, TokenType.Inequality, TokenType.Mod,
TokenType.Rem, TokenType.Lesser, TokenType.Greater, TokenType.LesserEqual, TokenType.GreaterEqual, TokenType.Rem, TokenType.Lesser, TokenType.Greater, TokenType.LesserEqual, TokenType.GreaterEqual,
TokenType.And, TokenType.Or)) { TokenType.And, TokenType.Or)) {
produce(NodeType.InfixOperation) { produce(NodeType.InfixOperation) {
attribution.adopt(expression)
val infixToken = next() val infixToken = next()
val infixOperator = ParserHelpers.convertInfixOperator(infixToken) val infixOperator = ParserHelpers.convertInfixOperator(infixToken)
InfixOperation(expression, infixOperator, parseExpression()) InfixOperation(expression, infixOperator, parseExpression())
@ -263,6 +274,16 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
IndexedBy(expression, index) IndexedBy(expression, index)
} }
override fun parseIndexedSetAssignment(): IndexedSetAssignment = produce(NodeType.IndexedSetAssignment) {
val target = parseExpression()
expect(TokenType.LeftBracket)
val index = parseExpression()
expect(TokenType.RightBracket)
expect(TokenType.Equals)
val value = parseExpression()
IndexedSetAssignment(target, index, value)
}
override fun parseInfixOperation(): InfixOperation = produce(NodeType.InfixOperation) { override fun parseInfixOperation(): InfixOperation = produce(NodeType.InfixOperation) {
val infixToken = next() val infixToken = next()
val infixOperator = ParserHelpers.convertInfixOperator(infixToken) val infixOperator = ParserHelpers.convertInfixOperator(infixToken)
@ -363,11 +384,11 @@ class Parser(source: TokenSource, attribution: NodeAttribution) :
Return(parseExpression()) Return(parseExpression())
} }
override fun parseSetAssignment(): SetAssignment = produce(NodeType.SetAssignment) { override fun parseSymbolSetAssignment(): SymbolSetAssignment = produce(NodeType.SymbolSetAssignment) {
val symbol = parseSymbol() val symbol = parseSymbol()
expect(TokenType.Equals) expect(TokenType.Equals)
val value = parseExpression() val value = parseExpression()
SetAssignment(symbol, value) SymbolSetAssignment(symbol, value)
} }
override fun parseStringLiteral(): StringLiteral = produce(NodeType.StringLiteral) { override fun parseStringLiteral(): StringLiteral = produce(NodeType.StringLiteral) {

View File

@ -202,7 +202,7 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
append(node.op.token) append(node.op.token)
} }
override fun visitSetAssignment(node: SetAssignment) { override fun visitSymbolSetAssignment(node: SymbolSetAssignment) {
visit(node.symbol) visit(node.symbol)
append(" = ") append(" = ")
visit(node.value) visit(node.value)
@ -304,6 +304,15 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
append("]") append("]")
} }
override fun visitIndexedSetAssignment(node: IndexedSetAssignment) {
visit(node.target)
append("[")
visit(node.index)
append("]")
append(" = ")
visit(node.value)
}
override fun visitCompilationUnit(node: CompilationUnit) { override fun visitCompilationUnit(node: CompilationUnit) {
for (declaration in node.declarations) { for (declaration in node.declarations) {
visit(declaration) visit(declaration)

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 IndexedSetAssignmentElement(node: ASTNode) : PorkElement(node) {
override fun getIcon(flags: Int): Icon? =
PorkElementHelpers.iconOf(this)
override fun getPresentation(): ItemPresentation? =
PorkElementHelpers.presentationOf(this)
}

View File

@ -16,7 +16,8 @@ object PorkElementFactory {
NodeType.CompilationUnit -> CompilationUnitElement(node) NodeType.CompilationUnit -> CompilationUnitElement(node)
NodeType.LetAssignment -> LetAssignmentElement(node) NodeType.LetAssignment -> LetAssignmentElement(node)
NodeType.VarAssignment -> VarAssignmentElement(node) NodeType.VarAssignment -> VarAssignmentElement(node)
NodeType.SetAssignment -> SetAssignmentElement(node) NodeType.SymbolSetAssignment -> SymbolSetAssignmentElement(node)
NodeType.IndexedSetAssignment -> IndexedSetAssignmentElement(node)
NodeType.InfixOperation -> InfixOperationElement(node) NodeType.InfixOperation -> InfixOperationElement(node)
NodeType.BooleanLiteral -> BooleanLiteralElement(node) NodeType.BooleanLiteral -> BooleanLiteralElement(node)
NodeType.FunctionCall -> FunctionCallElement(node) NodeType.FunctionCall -> FunctionCallElement(node)

View File

@ -6,7 +6,7 @@ import com.intellij.navigation.ItemPresentation
import gay.pizza.pork.idea.psi.PorkElementHelpers import gay.pizza.pork.idea.psi.PorkElementHelpers
import javax.swing.Icon import javax.swing.Icon
class SetAssignmentElement(node: ASTNode) : PorkElement(node) { class SymbolSetAssignmentElement(node: ASTNode) : PorkElement(node) {
override fun getIcon(flags: Int): Icon? = override fun getIcon(flags: Int): Icon? =
PorkElementHelpers.iconOf(this) PorkElementHelpers.iconOf(this)

View File

@ -15,6 +15,7 @@ val StandardOpHandlers: List<OpHandler> = listOf(
ListSizeOpHandler, ListSizeOpHandler,
IndexOpHandler, IndexOpHandler,
IndexSetOpHandler,
AndOpHandler, AndOpHandler,
OrOpHandler, OrOpHandler,

View File

@ -0,0 +1,15 @@
package gay.pizza.pork.vm.ops
import gay.pizza.pork.bytecode.Op
import gay.pizza.pork.bytecode.Opcode
import gay.pizza.pork.vm.InternalMachine
import gay.pizza.pork.vm.OpHandler
object IndexSetOpHandler : OpHandler(Opcode.IndexSet) {
override fun handle(machine: InternalMachine, op: Op) {
val list = machine.pop<MutableList<Any>>()
val index = machine.pop<Number>().toInt()
val value = machine.pop<Any>()
list[index] = value
}
}

View File

@ -13,6 +13,6 @@ object ListMakeOpHandler : OpHandler(Opcode.ListMake) {
val item = machine.popAnyValue() val item = machine.popAnyValue()
list.add(item) list.add(item)
} }
machine.push(list.reversed()) machine.push(list.reversed().toMutableList())
} }
} }