mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-02 21:00:56 +00:00
language: var, reassign, comparison operators
This commit is contained in:
parent
f433ba2776
commit
71999032ac
@ -41,6 +41,20 @@ types:
|
|||||||
type: Symbol
|
type: Symbol
|
||||||
- name: value
|
- name: value
|
||||||
type: Expression
|
type: Expression
|
||||||
|
VarAssignment:
|
||||||
|
parent: Expression
|
||||||
|
values:
|
||||||
|
- name: symbol
|
||||||
|
type: Symbol
|
||||||
|
- name: value
|
||||||
|
type: Expression
|
||||||
|
SetAssignment:
|
||||||
|
parent: Expression
|
||||||
|
values:
|
||||||
|
- name: symbol
|
||||||
|
type: Symbol
|
||||||
|
- name: value
|
||||||
|
type: Expression
|
||||||
InfixOperator:
|
InfixOperator:
|
||||||
values:
|
values:
|
||||||
- name: token
|
- name: token
|
||||||
@ -70,6 +84,18 @@ types:
|
|||||||
- name: Remainder
|
- name: Remainder
|
||||||
values:
|
values:
|
||||||
token: "rem"
|
token: "rem"
|
||||||
|
- name: Lesser
|
||||||
|
values:
|
||||||
|
token: "<"
|
||||||
|
- name: Greater
|
||||||
|
values:
|
||||||
|
token: ">"
|
||||||
|
- name: GreaterEqual
|
||||||
|
values:
|
||||||
|
token: ">="
|
||||||
|
- name: LesserEqual
|
||||||
|
values:
|
||||||
|
token: "<="
|
||||||
InfixOperation:
|
InfixOperation:
|
||||||
parent: Expression
|
parent: Expression
|
||||||
values:
|
values:
|
||||||
|
@ -8,6 +8,8 @@ digraph A {
|
|||||||
type_Block [shape=box,label="Block"]
|
type_Block [shape=box,label="Block"]
|
||||||
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_SetAssignment [shape=box,label="SetAssignment"]
|
||||||
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"]
|
||||||
@ -35,6 +37,8 @@ digraph A {
|
|||||||
type_Node -> type_CompilationUnit
|
type_Node -> type_CompilationUnit
|
||||||
type_Node -> type_Native
|
type_Node -> type_Native
|
||||||
type_Expression -> type_LetAssignment
|
type_Expression -> type_LetAssignment
|
||||||
|
type_Expression -> type_VarAssignment
|
||||||
|
type_Expression -> type_SetAssignment
|
||||||
type_Expression -> type_InfixOperation
|
type_Expression -> type_InfixOperation
|
||||||
type_Expression -> type_BooleanLiteral
|
type_Expression -> type_BooleanLiteral
|
||||||
type_Expression -> type_FunctionCall
|
type_Expression -> type_FunctionCall
|
||||||
@ -58,6 +62,10 @@ digraph A {
|
|||||||
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_VarAssignment -> type_Symbol [style=dotted]
|
||||||
|
type_VarAssignment -> type_Expression [style=dotted]
|
||||||
|
type_SetAssignment -> type_Symbol [style=dotted]
|
||||||
|
type_SetAssignment -> 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]
|
||||||
|
@ -14,5 +14,9 @@ enum class InfixOperator(val token: String) {
|
|||||||
Equals("=="),
|
Equals("=="),
|
||||||
NotEquals("!="),
|
NotEquals("!="),
|
||||||
EuclideanModulo("mod"),
|
EuclideanModulo("mod"),
|
||||||
Remainder("rem")
|
Remainder("rem"),
|
||||||
|
Lesser("<"),
|
||||||
|
Greater(">"),
|
||||||
|
GreaterEqual(">="),
|
||||||
|
LesserEqual("<=")
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,9 @@ class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor<Unit> {
|
|||||||
override fun visitPrefixOperation(node: PrefixOperation): Unit =
|
override fun visitPrefixOperation(node: PrefixOperation): 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)
|
||||||
|
|
||||||
@ -62,6 +65,9 @@ class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor<Unit> {
|
|||||||
override fun visitSymbolReference(node: SymbolReference): Unit =
|
override fun visitSymbolReference(node: SymbolReference): Unit =
|
||||||
handle(node)
|
handle(node)
|
||||||
|
|
||||||
|
override fun visitVarAssignment(node: VarAssignment): Unit =
|
||||||
|
handle(node)
|
||||||
|
|
||||||
override fun visitWhile(node: While): Unit =
|
override fun visitWhile(node: While): Unit =
|
||||||
handle(node)
|
handle(node)
|
||||||
|
|
||||||
|
@ -23,8 +23,10 @@ enum class NodeType(val parent: NodeType? = null) {
|
|||||||
Native(Node),
|
Native(Node),
|
||||||
Parentheses(Expression),
|
Parentheses(Expression),
|
||||||
PrefixOperation(Expression),
|
PrefixOperation(Expression),
|
||||||
|
SetAssignment(Expression),
|
||||||
StringLiteral(Expression),
|
StringLiteral(Expression),
|
||||||
Symbol(Node),
|
Symbol(Node),
|
||||||
SymbolReference(Expression),
|
SymbolReference(Expression),
|
||||||
|
VarAssignment(Expression),
|
||||||
While(Expression)
|
While(Expression)
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,15 @@ interface NodeVisitor<T> {
|
|||||||
|
|
||||||
fun visitPrefixOperation(node: PrefixOperation): T
|
fun visitPrefixOperation(node: PrefixOperation): T
|
||||||
|
|
||||||
|
fun visitSetAssignment(node: SetAssignment): T
|
||||||
|
|
||||||
fun visitStringLiteral(node: StringLiteral): T
|
fun visitStringLiteral(node: StringLiteral): T
|
||||||
|
|
||||||
fun visitSymbol(node: Symbol): T
|
fun visitSymbol(node: Symbol): T
|
||||||
|
|
||||||
fun visitSymbolReference(node: SymbolReference): T
|
fun visitSymbolReference(node: SymbolReference): T
|
||||||
|
|
||||||
|
fun visitVarAssignment(node: VarAssignment): T
|
||||||
|
|
||||||
fun visitWhile(node: While): T
|
fun visitWhile(node: While): T
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ fun <T> NodeVisitor<T>.visit(node: Node): T =
|
|||||||
is Block -> visitBlock(node)
|
is Block -> visitBlock(node)
|
||||||
is CompilationUnit -> visitCompilationUnit(node)
|
is CompilationUnit -> visitCompilationUnit(node)
|
||||||
is LetAssignment -> visitLetAssignment(node)
|
is LetAssignment -> visitLetAssignment(node)
|
||||||
|
is VarAssignment -> visitVarAssignment(node)
|
||||||
|
is SetAssignment -> visitSetAssignment(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)
|
||||||
|
29
ast/src/main/kotlin/gay/pizza/pork/ast/SetAssignment.kt
Normal file
29
ast/src/main/kotlin/gay/pizza/pork/ast/SetAssignment.kt
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// GENERATED CODE FROM PORK AST CODEGEN
|
||||||
|
package gay.pizza.pork.ast
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("setAssignment")
|
||||||
|
class SetAssignment(val symbol: Symbol, val value: Expression) : Expression() {
|
||||||
|
override val type: NodeType = NodeType.SetAssignment
|
||||||
|
|
||||||
|
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||||
|
visitor.visitNodes(symbol, value)
|
||||||
|
|
||||||
|
override fun <T> visit(visitor: NodeVisitor<T>): T =
|
||||||
|
visitor.visitSetAssignment(this)
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is SetAssignment) return false
|
||||||
|
return other.symbol == symbol && other.value == value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = symbol.hashCode()
|
||||||
|
result = 31 * result + value.hashCode()
|
||||||
|
result = 31 * result + type.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
29
ast/src/main/kotlin/gay/pizza/pork/ast/VarAssignment.kt
Normal file
29
ast/src/main/kotlin/gay/pizza/pork/ast/VarAssignment.kt
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// GENERATED CODE FROM PORK AST CODEGEN
|
||||||
|
package gay.pizza.pork.ast
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("varAssignment")
|
||||||
|
class VarAssignment(val symbol: Symbol, val value: Expression) : Expression() {
|
||||||
|
override val type: NodeType = NodeType.VarAssignment
|
||||||
|
|
||||||
|
override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
|
||||||
|
visitor.visitNodes(symbol, value)
|
||||||
|
|
||||||
|
override fun <T> visit(visitor: NodeVisitor<T>): T =
|
||||||
|
visitor.visitVarAssignment(this)
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is VarAssignment) return false
|
||||||
|
return other.symbol == symbol && other.value == value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = symbol.hashCode()
|
||||||
|
result = 31 * result + value.hashCode()
|
||||||
|
result = 31 * result + type.hashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
@ -26,13 +26,19 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
|
|
||||||
override fun visitLetAssignment(node: LetAssignment): Any {
|
override fun visitLetAssignment(node: LetAssignment): Any {
|
||||||
val value = node.value.visit(this)
|
val value = node.value.visit(this)
|
||||||
currentScope.define(node.symbol.id, value)
|
currentScope.define(node.symbol.id, value, ValueStoreType.Let)
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSymbolReference(node: SymbolReference): Any =
|
override fun visitSymbolReference(node: SymbolReference): Any =
|
||||||
currentScope.value(node.symbol.id)
|
currentScope.value(node.symbol.id)
|
||||||
|
|
||||||
|
override fun visitVarAssignment(node: VarAssignment): Any {
|
||||||
|
val value = node.value.visit(this)
|
||||||
|
currentScope.define(node.symbol.id, value, type = ValueStoreType.Var)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitWhile(node: While): Any {
|
override fun visitWhile(node: While): Any {
|
||||||
val blockFunction = node.block.visit(this) as BlockFunction
|
val blockFunction = node.block.visit(this) as BlockFunction
|
||||||
var result: Any? = null
|
var result: Any? = null
|
||||||
@ -68,6 +74,12 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitSetAssignment(node: SetAssignment): Any {
|
||||||
|
val value = node.value.visit(this)
|
||||||
|
currentScope.set(node.symbol.id, value)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitIf(node: If): Any {
|
override fun visitIf(node: If): Any {
|
||||||
val condition = node.condition.visit(this)
|
val condition = node.condition.visit(this)
|
||||||
return if (condition == true) {
|
return if (condition == true) {
|
||||||
@ -108,7 +120,11 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
multiply = { a, b -> a * b },
|
multiply = { a, b -> a * b },
|
||||||
divide = { a, b -> a / b },
|
divide = { a, b -> a / b },
|
||||||
euclideanModulo = { _, _ -> throw RuntimeException("Can't perform integer modulo between floating point types") },
|
euclideanModulo = { _, _ -> throw RuntimeException("Can't perform integer modulo between floating point types") },
|
||||||
remainder = { _, _ -> throw RuntimeException("Can't perform integer remainder between floating point types") }
|
remainder = { _, _ -> throw RuntimeException("Can't perform integer remainder between floating point types") },
|
||||||
|
lesser = { a, b -> a < b },
|
||||||
|
greater = { a, b -> a > b },
|
||||||
|
lesserEqual = { a, b -> a <= b },
|
||||||
|
greaterEqual = { a, b -> a >= b }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +139,11 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
multiply = { a, b -> a * b },
|
multiply = { a, b -> a * b },
|
||||||
divide = { a, b -> a / b },
|
divide = { a, b -> a / b },
|
||||||
euclideanModulo = { _, _ -> throw RuntimeException("Can't perform integer modulo between floating point types") },
|
euclideanModulo = { _, _ -> throw RuntimeException("Can't perform integer modulo between floating point types") },
|
||||||
remainder = { _, _ -> throw RuntimeException("Can't perform integer remainder between floating point types") }
|
remainder = { _, _ -> throw RuntimeException("Can't perform integer remainder between floating point types") },
|
||||||
|
lesser = { a, b -> a < b },
|
||||||
|
greater = { a, b -> a > b },
|
||||||
|
lesserEqual = { a, b -> a <= b },
|
||||||
|
greaterEqual = { a, b -> a >= b }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +158,11 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
multiply = { a, b -> a * b },
|
multiply = { a, b -> a * b },
|
||||||
divide = { a, b -> a / b },
|
divide = { a, b -> a / b },
|
||||||
euclideanModulo = { x, d -> (x % d).let { q -> if (q < 0) q + abs(d) else q } },
|
euclideanModulo = { x, d -> (x % d).let { q -> if (q < 0) q + abs(d) else q } },
|
||||||
remainder = { x, d -> x % d }
|
remainder = { x, d -> x % d },
|
||||||
|
lesser = { a, b -> a < b },
|
||||||
|
greater = { a, b -> a > b },
|
||||||
|
lesserEqual = { a, b -> a <= b },
|
||||||
|
greaterEqual = { a, b -> a >= b }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +177,11 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
multiply = { a, b -> a * b },
|
multiply = { a, b -> a * b },
|
||||||
divide = { a, b -> a / b },
|
divide = { a, b -> a / b },
|
||||||
euclideanModulo = { x, d -> (x % d).let { q -> if (q < 0) q + abs(d) else q } },
|
euclideanModulo = { x, d -> (x % d).let { q -> if (q < 0) q + abs(d) else q } },
|
||||||
remainder = { x, d -> x % d }
|
remainder = { x, d -> x % d },
|
||||||
|
lesser = { a, b -> a < b },
|
||||||
|
greater = { a, b -> a > b },
|
||||||
|
lesserEqual = { a, b -> a <= b },
|
||||||
|
greaterEqual = { a, b -> a >= b }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,8 +198,12 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
multiply: (T, T) -> T,
|
multiply: (T, T) -> T,
|
||||||
divide: (T, T) -> T,
|
divide: (T, T) -> T,
|
||||||
euclideanModulo: (T, T) -> T,
|
euclideanModulo: (T, T) -> T,
|
||||||
remainder: (T, T) -> T
|
remainder: (T, T) -> T,
|
||||||
): T {
|
lesser: (T, T) -> Boolean,
|
||||||
|
greater: (T, T) -> Boolean,
|
||||||
|
lesserEqual: (T, T) -> Boolean,
|
||||||
|
greaterEqual: (T, T) -> Boolean
|
||||||
|
): Any {
|
||||||
return when (op) {
|
return when (op) {
|
||||||
InfixOperator.Plus -> add(convert(left), convert(right))
|
InfixOperator.Plus -> add(convert(left), convert(right))
|
||||||
InfixOperator.Minus -> subtract(convert(left), convert(right))
|
InfixOperator.Minus -> subtract(convert(left), convert(right))
|
||||||
@ -179,6 +211,10 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
InfixOperator.Divide -> divide(convert(left), convert(right))
|
InfixOperator.Divide -> divide(convert(left), convert(right))
|
||||||
InfixOperator.EuclideanModulo -> euclideanModulo(convert(left), convert(right))
|
InfixOperator.EuclideanModulo -> euclideanModulo(convert(left), convert(right))
|
||||||
InfixOperator.Remainder -> remainder(convert(left), convert(right))
|
InfixOperator.Remainder -> remainder(convert(left), convert(right))
|
||||||
|
InfixOperator.Lesser -> lesser(convert(left), convert(right))
|
||||||
|
InfixOperator.Greater -> greater(convert(left), convert(right))
|
||||||
|
InfixOperator.LesserEqual -> lesserEqual(convert(left), convert(right))
|
||||||
|
InfixOperator.GreaterEqual -> greaterEqual(convert(left), convert(right))
|
||||||
else -> throw RuntimeException("Unable to handle operation $op")
|
else -> throw RuntimeException("Unable to handle operation $op")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,43 +6,55 @@ class Scope(
|
|||||||
val name: String? = null
|
val name: String? = null
|
||||||
) {
|
) {
|
||||||
private val inherited = inherits.toMutableList()
|
private val inherited = inherits.toMutableList()
|
||||||
private val variables = mutableMapOf<String, Any>()
|
private val variables = mutableMapOf<String, ValueStore>()
|
||||||
|
|
||||||
fun define(name: String, value: Any) {
|
fun define(name: String, value: Any, type: ValueStoreType = ValueStoreType.Let) {
|
||||||
val previous = variables.put(name, value)
|
val previous = variables.put(name, ValueStore(value, type))
|
||||||
if (previous != null) {
|
if (previous != null) {
|
||||||
variables[name] = previous
|
variables[name] = previous
|
||||||
throw RuntimeException("Variable '${name}' is already defined")
|
throw RuntimeException("Variable '${name}' is already defined")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun value(name: String): Any {
|
fun set(name: String, value: Any) {
|
||||||
val value = valueOrNotFound(name)
|
val holder = valueHolderOrNotFound(name)
|
||||||
if (value === NotFound) {
|
if (holder.type == ValueStoreType.Let) {
|
||||||
|
throw RuntimeException("Variable '${name}' is already defined")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (holder === NotFound.Holder) {
|
||||||
throw RuntimeException("Variable '${name}' not defined")
|
throw RuntimeException("Variable '${name}' not defined")
|
||||||
}
|
}
|
||||||
return value
|
holder.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun valueOrNotFound(name: String): Any {
|
fun value(name: String): Any {
|
||||||
val value = variables[name]
|
val holder = valueHolderOrNotFound(name)
|
||||||
if (value == null) {
|
if (holder === NotFound.Holder) {
|
||||||
|
throw RuntimeException("Variable '${name}' not defined")
|
||||||
|
}
|
||||||
|
return holder.value
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun valueHolderOrNotFound(name: String): ValueStore {
|
||||||
|
val holder = variables[name]
|
||||||
|
if (holder == null) {
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
val parentMaybeFound = parent.valueOrNotFound(name)
|
val parentMaybeFound = parent.valueHolderOrNotFound(name)
|
||||||
if (parentMaybeFound !== NotFound) {
|
if (parentMaybeFound !== NotFound.Holder) {
|
||||||
return parentMaybeFound
|
return parentMaybeFound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (inherit in inherited) {
|
for (inherit in inherited) {
|
||||||
val inheritMaybeFound = inherit.valueOrNotFound(name)
|
val inheritMaybeFound = inherit.valueHolderOrNotFound(name)
|
||||||
if (inheritMaybeFound !== NotFound) {
|
if (inheritMaybeFound !== NotFound.Holder) {
|
||||||
return inheritMaybeFound
|
return inheritMaybeFound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NotFound
|
return NotFound.Holder
|
||||||
}
|
}
|
||||||
return value
|
return holder
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fork(name: String? = null): Scope =
|
fun fork(name: String? = null): Scope =
|
||||||
@ -80,5 +92,7 @@ class Scope(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private object NotFound
|
private object NotFound {
|
||||||
|
val Holder = ValueStore(NotFound, ValueStoreType.Let)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package gay.pizza.pork.evaluator
|
||||||
|
|
||||||
|
class ValueStore(var value: Any, val type: ValueStoreType) {
|
||||||
|
override fun toString(): String = "${type.name}: $value"
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package gay.pizza.pork.evaluator
|
||||||
|
|
||||||
|
enum class ValueStoreType {
|
||||||
|
Let,
|
||||||
|
Var
|
||||||
|
}
|
7
examples/count.pork
Normal file
7
examples/count.pork
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export func main() {
|
||||||
|
var x = 1
|
||||||
|
while x <= 5 {
|
||||||
|
println(x)
|
||||||
|
x = x + 1
|
||||||
|
}
|
||||||
|
}
|
@ -5,5 +5,6 @@ import gay.pizza.pork.ast.Node
|
|||||||
object DiscardNodeAttribution : NodeAttribution {
|
object DiscardNodeAttribution : NodeAttribution {
|
||||||
override fun enter() {}
|
override fun enter() {}
|
||||||
override fun push(token: Token) {}
|
override fun push(token: Token) {}
|
||||||
|
override fun <T : Node> adopt(node: T) {}
|
||||||
override fun <T : Node> exit(node: T): T = node
|
override fun <T : Node> exit(node: T): T = node
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,6 @@ import gay.pizza.pork.ast.Node
|
|||||||
interface NodeAttribution {
|
interface NodeAttribution {
|
||||||
fun enter()
|
fun enter()
|
||||||
fun push(token: Token)
|
fun push(token: Token)
|
||||||
|
fun <T: Node> adopt(node: T)
|
||||||
fun <T: Node> exit(node: T): T
|
fun <T: Node> exit(node: T): T
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,14 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
LetAssignment(symbol, value)
|
LetAssignment(symbol, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun readVarAssignment(): VarAssignment = within {
|
||||||
|
expect(TokenType.Var)
|
||||||
|
val symbol = readSymbolRaw()
|
||||||
|
expect(TokenType.Equals)
|
||||||
|
val value = readExpression()
|
||||||
|
VarAssignment(symbol, value)
|
||||||
|
}
|
||||||
|
|
||||||
private fun readSymbolRaw(): Symbol = within {
|
private fun readSymbolRaw(): Symbol = within {
|
||||||
expect(TokenType.Symbol) { Symbol(it.text) }
|
expect(TokenType.Symbol) { Symbol(it.text) }
|
||||||
}
|
}
|
||||||
@ -123,6 +131,10 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
readLetAssignment()
|
readLetAssignment()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TokenType.Var -> {
|
||||||
|
readVarAssignment()
|
||||||
|
}
|
||||||
|
|
||||||
TokenType.Symbol -> {
|
TokenType.Symbol -> {
|
||||||
readSymbolCases()
|
readSymbolCases()
|
||||||
}
|
}
|
||||||
@ -161,6 +173,15 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (expression is SymbolReference && peek(TokenType.Equals)) {
|
||||||
|
return within {
|
||||||
|
attribution.adopt(expression)
|
||||||
|
expect(TokenType.Equals)
|
||||||
|
val value = readExpression()
|
||||||
|
SetAssignment(expression.symbol, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return if (peek(
|
return if (peek(
|
||||||
TokenType.Plus,
|
TokenType.Plus,
|
||||||
TokenType.Minus,
|
TokenType.Minus,
|
||||||
@ -169,7 +190,11 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
TokenType.Equality,
|
TokenType.Equality,
|
||||||
TokenType.Inequality,
|
TokenType.Inequality,
|
||||||
TokenType.Mod,
|
TokenType.Mod,
|
||||||
TokenType.Rem
|
TokenType.Rem,
|
||||||
|
TokenType.Lesser,
|
||||||
|
TokenType.Greater,
|
||||||
|
TokenType.LesserEqual,
|
||||||
|
TokenType.GreaterEqual
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
within {
|
within {
|
||||||
@ -268,6 +293,10 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
TokenType.Inequality -> InfixOperator.NotEquals
|
TokenType.Inequality -> InfixOperator.NotEquals
|
||||||
TokenType.Mod -> InfixOperator.EuclideanModulo
|
TokenType.Mod -> InfixOperator.EuclideanModulo
|
||||||
TokenType.Rem -> InfixOperator.Remainder
|
TokenType.Rem -> InfixOperator.Remainder
|
||||||
|
TokenType.Lesser -> InfixOperator.Lesser
|
||||||
|
TokenType.Greater -> InfixOperator.Greater
|
||||||
|
TokenType.LesserEqual -> InfixOperator.LesserEqual
|
||||||
|
TokenType.GreaterEqual -> InfixOperator.GreaterEqual
|
||||||
else -> throw RuntimeException("Unknown Infix Operator")
|
else -> throw RuntimeException("Unknown Infix Operator")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +95,13 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
|
|||||||
visit(node.symbol)
|
visit(node.symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitVarAssignment(node: VarAssignment) {
|
||||||
|
append("var ")
|
||||||
|
visit(node.symbol)
|
||||||
|
append(" = ")
|
||||||
|
visit(node.value)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitWhile(node: While) {
|
override fun visitWhile(node: While) {
|
||||||
append("while ")
|
append("while ")
|
||||||
visit(node.condition)
|
visit(node.condition)
|
||||||
@ -113,6 +120,12 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
|
|||||||
visit(node.expression)
|
visit(node.expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitSetAssignment(node: SetAssignment) {
|
||||||
|
visit(node.symbol)
|
||||||
|
append(" = ")
|
||||||
|
visit(node.value)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitIf(node: If) {
|
override fun visitIf(node: If) {
|
||||||
append("if ")
|
append("if ")
|
||||||
visit(node.condition)
|
visit(node.condition)
|
||||||
|
@ -22,6 +22,15 @@ class TokenNodeAttribution : NodeAttribution {
|
|||||||
store.add(token)
|
store.add(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun <T : Node> adopt(node: T) {
|
||||||
|
val tokens = nodes.remove(node)
|
||||||
|
if (tokens != null) {
|
||||||
|
for (token in tokens) {
|
||||||
|
push(token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun <T: Node> exit(node: T): T {
|
override fun <T: Node> exit(node: T): T {
|
||||||
val store = stack.removeLast()
|
val store = stack.removeLast()
|
||||||
nodes[node] = store
|
nodes[node] = store
|
||||||
|
@ -19,6 +19,10 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
|||||||
Minus(SingleChar('-'), OperatorFamily),
|
Minus(SingleChar('-'), OperatorFamily),
|
||||||
Multiply(SingleChar('*'), OperatorFamily),
|
Multiply(SingleChar('*'), OperatorFamily),
|
||||||
Divide(SingleChar('/'), OperatorFamily),
|
Divide(SingleChar('/'), OperatorFamily),
|
||||||
|
LesserEqual(OperatorFamily),
|
||||||
|
GreaterEqual(OperatorFamily),
|
||||||
|
Lesser(SingleChar('<'), OperatorFamily, Promotion('=', LesserEqual)),
|
||||||
|
Greater(SingleChar('>'), OperatorFamily, Promotion('=', GreaterEqual)),
|
||||||
LeftCurly(SingleChar('{')),
|
LeftCurly(SingleChar('{')),
|
||||||
RightCurly(SingleChar('}')),
|
RightCurly(SingleChar('}')),
|
||||||
LeftBracket(SingleChar('[')),
|
LeftBracket(SingleChar('[')),
|
||||||
@ -42,6 +46,7 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
|||||||
Func(Keyword("func"), KeywordFamily),
|
Func(Keyword("func"), KeywordFamily),
|
||||||
Native(Keyword("native"), KeywordFamily),
|
Native(Keyword("native"), KeywordFamily),
|
||||||
Let(Keyword("let"), KeywordFamily),
|
Let(Keyword("let"), KeywordFamily),
|
||||||
|
Var(Keyword("var"), KeywordFamily),
|
||||||
Whitespace(CharConsumer { it == ' ' || it == '\r' || it == '\n' || it == '\t' }),
|
Whitespace(CharConsumer { it == ' ' || it == '\r' || it == '\n' || it == '\t' }),
|
||||||
BlockComment(CommentFamily),
|
BlockComment(CommentFamily),
|
||||||
LineComment(CommentFamily),
|
LineComment(CommentFamily),
|
||||||
|
Loading…
Reference in New Issue
Block a user