mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-02 21:00:56 +00:00
implement support for setting indexed values
This commit is contained in:
parent
48e19a8068
commit
3dcac2f9e6
@ -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
|
||||||
|
@ -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]
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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),
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
@ -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!!)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
@ -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))
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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])
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
}
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
|
@ -15,6 +15,7 @@ val StandardOpHandlers: List<OpHandler> = listOf(
|
|||||||
ListSizeOpHandler,
|
ListSizeOpHandler,
|
||||||
|
|
||||||
IndexOpHandler,
|
IndexOpHandler,
|
||||||
|
IndexSetOpHandler,
|
||||||
|
|
||||||
AndOpHandler,
|
AndOpHandler,
|
||||||
OrOpHandler,
|
OrOpHandler,
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user