mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 05:10:55 +00:00
language: add binary operators
- unary binary not - infix bitwise and - infix bitwise or - infix bitwise exclusive or (xor)
This commit is contained in:
@ -96,6 +96,15 @@ types:
|
|||||||
- name: LesserEqual
|
- name: LesserEqual
|
||||||
values:
|
values:
|
||||||
token: "<="
|
token: "<="
|
||||||
|
- name: BinaryAnd
|
||||||
|
values:
|
||||||
|
token: "&"
|
||||||
|
- name: BinaryOr
|
||||||
|
values:
|
||||||
|
token: "|"
|
||||||
|
- name: BinaryExclusiveOr
|
||||||
|
values:
|
||||||
|
token: "^"
|
||||||
InfixOperation:
|
InfixOperation:
|
||||||
parent: Expression
|
parent: Expression
|
||||||
values:
|
values:
|
||||||
@ -196,6 +205,9 @@ types:
|
|||||||
- name: UnaryMinus
|
- name: UnaryMinus
|
||||||
values:
|
values:
|
||||||
token: "-"
|
token: "-"
|
||||||
|
- name: BinaryNot
|
||||||
|
values:
|
||||||
|
token: "~"
|
||||||
PrefixOperation:
|
PrefixOperation:
|
||||||
parent: Expression
|
parent: Expression
|
||||||
values:
|
values:
|
||||||
|
@ -18,5 +18,8 @@ enum class InfixOperator(val token: String) {
|
|||||||
Lesser("<"),
|
Lesser("<"),
|
||||||
Greater(">"),
|
Greater(">"),
|
||||||
GreaterEqual(">="),
|
GreaterEqual(">="),
|
||||||
LesserEqual("<=")
|
LesserEqual("<="),
|
||||||
|
BinaryAnd("&"),
|
||||||
|
BinaryOr("|"),
|
||||||
|
BinaryExclusiveOr("^")
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,6 @@ import kotlinx.serialization.Serializable
|
|||||||
enum class PrefixOperator(val token: String) {
|
enum class PrefixOperator(val token: String) {
|
||||||
Negate("!"),
|
Negate("!"),
|
||||||
UnaryPlus("+"),
|
UnaryPlus("+"),
|
||||||
UnaryMinus("-")
|
UnaryMinus("-"),
|
||||||
|
BinaryNot("~")
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
}
|
}
|
||||||
!value
|
!value
|
||||||
}
|
}
|
||||||
PrefixOperator.UnaryPlus, PrefixOperator.UnaryMinus -> {
|
PrefixOperator.UnaryPlus, PrefixOperator.UnaryMinus, PrefixOperator.BinaryNot -> {
|
||||||
if (value !is Number) {
|
if (value !is Number) {
|
||||||
throw RuntimeException("Numeric unary '${node.op.token}' illegal on non-numeric type '${value.javaClass.simpleName}'")
|
throw RuntimeException("Numeric unary '${node.op.token}' illegal on non-numeric type '${value.javaClass.simpleName}'")
|
||||||
}
|
}
|
||||||
@ -91,7 +91,8 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
value,
|
value,
|
||||||
convert = { it.toDouble() },
|
convert = { it.toDouble() },
|
||||||
plus = { +it },
|
plus = { +it },
|
||||||
minus = { -it }
|
minus = { -it },
|
||||||
|
binaryNot = unaryFloatingPointTypeError("binary not")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is Float -> {
|
is Float -> {
|
||||||
@ -100,7 +101,8 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
value,
|
value,
|
||||||
convert = { it.toFloat() },
|
convert = { it.toFloat() },
|
||||||
plus = { +it },
|
plus = { +it },
|
||||||
minus = { -it }
|
minus = { -it },
|
||||||
|
binaryNot = unaryFloatingPointTypeError("binary not")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is Long -> {
|
is Long -> {
|
||||||
@ -109,7 +111,8 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
value,
|
value,
|
||||||
convert = { it.toLong() },
|
convert = { it.toLong() },
|
||||||
plus = { +it },
|
plus = { +it },
|
||||||
minus = { -it }
|
minus = { -it },
|
||||||
|
binaryNot = { it.inv() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is Int -> {
|
is Int -> {
|
||||||
@ -118,7 +121,8 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
value,
|
value,
|
||||||
convert = { it.toInt() },
|
convert = { it.toInt() },
|
||||||
plus = { +it },
|
plus = { +it },
|
||||||
minus = { -it }
|
minus = { -it },
|
||||||
|
binaryNot = { it.inv() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> throw RuntimeException("Unknown numeric type: ${value.javaClass.name}")
|
else -> throw RuntimeException("Unknown numeric type: ${value.javaClass.name}")
|
||||||
@ -179,6 +183,9 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
subtract = { a, b -> a - b },
|
subtract = { a, b -> a - b },
|
||||||
multiply = { a, b -> a * b },
|
multiply = { a, b -> a * b },
|
||||||
divide = { a, b -> a / b },
|
divide = { a, b -> a / b },
|
||||||
|
binaryAnd = { _, _ -> floatingPointTypeError("binary and") },
|
||||||
|
binaryOr = { _, _ -> floatingPointTypeError("binary or") },
|
||||||
|
binaryExclusiveOr = { _, _ -> floatingPointTypeError("binary exclusive-or") },
|
||||||
euclideanModulo = { _, _ -> floatingPointTypeError("integer modulo") },
|
euclideanModulo = { _, _ -> floatingPointTypeError("integer modulo") },
|
||||||
remainder = { _, _ -> floatingPointTypeError("integer remainder") },
|
remainder = { _, _ -> floatingPointTypeError("integer remainder") },
|
||||||
lesser = { a, b -> a < b },
|
lesser = { a, b -> a < b },
|
||||||
@ -198,6 +205,9 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
subtract = { a, b -> a - b },
|
subtract = { a, b -> a - b },
|
||||||
multiply = { a, b -> a * b },
|
multiply = { a, b -> a * b },
|
||||||
divide = { a, b -> a / b },
|
divide = { a, b -> a / b },
|
||||||
|
binaryAnd = { _, _ -> floatingPointTypeError("binary and") },
|
||||||
|
binaryOr = { _, _ -> floatingPointTypeError("binary or") },
|
||||||
|
binaryExclusiveOr = { _, _ -> floatingPointTypeError("binary exclusive-or") },
|
||||||
euclideanModulo = { _, _ -> floatingPointTypeError("integer modulo") },
|
euclideanModulo = { _, _ -> floatingPointTypeError("integer modulo") },
|
||||||
remainder = { _, _ -> floatingPointTypeError("integer remainder") },
|
remainder = { _, _ -> floatingPointTypeError("integer remainder") },
|
||||||
lesser = { a, b -> a < b },
|
lesser = { a, b -> a < b },
|
||||||
@ -217,6 +227,9 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
subtract = { a, b -> a - b },
|
subtract = { a, b -> a - b },
|
||||||
multiply = { a, b -> a * b },
|
multiply = { a, b -> a * b },
|
||||||
divide = { a, b -> a / b },
|
divide = { a, b -> a / b },
|
||||||
|
binaryAnd = { a, b -> a and b },
|
||||||
|
binaryOr = { a, b -> a or b },
|
||||||
|
binaryExclusiveOr = { a, b -> a xor 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 },
|
lesser = { a, b -> a < b },
|
||||||
@ -236,6 +249,9 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
subtract = { a, b -> a - b },
|
subtract = { a, b -> a - b },
|
||||||
multiply = { a, b -> a * b },
|
multiply = { a, b -> a * b },
|
||||||
divide = { a, b -> a / b },
|
divide = { a, b -> a / b },
|
||||||
|
binaryAnd = { a, b -> a and b },
|
||||||
|
binaryOr = { a, b -> a or b },
|
||||||
|
binaryExclusiveOr = { a, b -> a xor 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 },
|
lesser = { a, b -> a < b },
|
||||||
@ -257,6 +273,9 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
subtract: (T, T) -> T,
|
subtract: (T, T) -> T,
|
||||||
multiply: (T, T) -> T,
|
multiply: (T, T) -> T,
|
||||||
divide: (T, T) -> T,
|
divide: (T, T) -> T,
|
||||||
|
binaryAnd: (T, T) -> T,
|
||||||
|
binaryOr: (T, T) -> T,
|
||||||
|
binaryExclusiveOr: (T, T) -> T,
|
||||||
euclideanModulo: (T, T) -> T,
|
euclideanModulo: (T, T) -> T,
|
||||||
remainder: (T, T) -> T,
|
remainder: (T, T) -> T,
|
||||||
lesser: (T, T) -> Boolean,
|
lesser: (T, T) -> Boolean,
|
||||||
@ -269,13 +288,16 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
InfixOperator.Minus -> subtract(convert(left), convert(right))
|
InfixOperator.Minus -> subtract(convert(left), convert(right))
|
||||||
InfixOperator.Multiply -> multiply(convert(left), convert(right))
|
InfixOperator.Multiply -> multiply(convert(left), convert(right))
|
||||||
InfixOperator.Divide -> divide(convert(left), convert(right))
|
InfixOperator.Divide -> divide(convert(left), convert(right))
|
||||||
|
InfixOperator.Equals, InfixOperator.NotEquals -> throw RuntimeException("Unable to handle operation $op")
|
||||||
|
InfixOperator.BinaryAnd -> binaryAnd(convert(left), convert(right))
|
||||||
|
InfixOperator.BinaryOr -> binaryOr(convert(left), convert(right))
|
||||||
|
InfixOperator.BinaryExclusiveOr -> binaryExclusiveOr(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.Lesser -> lesser(convert(left), convert(right))
|
||||||
InfixOperator.Greater -> greater(convert(left), convert(right))
|
InfixOperator.Greater -> greater(convert(left), convert(right))
|
||||||
InfixOperator.LesserEqual -> lesserEqual(convert(left), convert(right))
|
InfixOperator.LesserEqual -> lesserEqual(convert(left), convert(right))
|
||||||
InfixOperator.GreaterEqual -> greaterEqual(convert(left), convert(right))
|
InfixOperator.GreaterEqual -> greaterEqual(convert(left), convert(right))
|
||||||
else -> throw RuntimeException("Unable to handle operation $op")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,12 +306,14 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
value: Number,
|
value: Number,
|
||||||
convert: (Number) -> T,
|
convert: (Number) -> T,
|
||||||
plus: (T) -> T,
|
plus: (T) -> T,
|
||||||
minus: (T) -> T
|
minus: (T) -> T,
|
||||||
|
binaryNot: (T) -> T
|
||||||
): Any {
|
): Any {
|
||||||
return when (op) {
|
return when (op) {
|
||||||
|
PrefixOperator.Negate -> throw RuntimeException("Unable to handle operation $op")
|
||||||
PrefixOperator.UnaryPlus -> plus(convert(value))
|
PrefixOperator.UnaryPlus -> plus(convert(value))
|
||||||
PrefixOperator.UnaryMinus -> minus(convert(value))
|
PrefixOperator.UnaryMinus -> minus(convert(value))
|
||||||
else -> throw RuntimeException("Unable to handle operation $op")
|
PrefixOperator.BinaryNot -> binaryNot(convert(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,6 +352,10 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun unaryFloatingPointTypeError(operation: String): Nothing {
|
||||||
|
throw RuntimeException("Can't perform $operation on a floating point type")
|
||||||
|
}
|
||||||
|
|
||||||
private fun floatingPointTypeError(operation: String): Nothing {
|
private fun floatingPointTypeError(operation: String): Nothing {
|
||||||
throw RuntimeException("Can't perform $operation between floating point types")
|
throw RuntimeException("Can't perform $operation between floating point types")
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun readPrefixOperation(): PrefixOperation = within {
|
private fun readPrefixOperation(): PrefixOperation = within {
|
||||||
expect(TokenType.Negation, TokenType.Plus, TokenType.Minus) {
|
expect(TokenType.Negation, TokenType.Plus, TokenType.Minus, TokenType.Tilde) {
|
||||||
PrefixOperation(convertPrefixOperator(it), readExpression())
|
PrefixOperation(convertPrefixOperator(it), readExpression())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
readParentheses()
|
readParentheses()
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenType.Negation, TokenType.Plus, TokenType.Minus -> {
|
TokenType.Negation, TokenType.Plus, TokenType.Minus, TokenType.Tilde -> {
|
||||||
readPrefixOperation()
|
readPrefixOperation()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,6 +192,9 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
TokenType.Minus,
|
TokenType.Minus,
|
||||||
TokenType.Multiply,
|
TokenType.Multiply,
|
||||||
TokenType.Divide,
|
TokenType.Divide,
|
||||||
|
TokenType.Ampersand,
|
||||||
|
TokenType.Pipe,
|
||||||
|
TokenType.Caret,
|
||||||
TokenType.Equality,
|
TokenType.Equality,
|
||||||
TokenType.Inequality,
|
TokenType.Inequality,
|
||||||
TokenType.Mod,
|
TokenType.Mod,
|
||||||
@ -311,6 +314,9 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
TokenType.Minus -> InfixOperator.Minus
|
TokenType.Minus -> InfixOperator.Minus
|
||||||
TokenType.Multiply -> InfixOperator.Multiply
|
TokenType.Multiply -> InfixOperator.Multiply
|
||||||
TokenType.Divide -> InfixOperator.Divide
|
TokenType.Divide -> InfixOperator.Divide
|
||||||
|
TokenType.Ampersand -> InfixOperator.BinaryAnd
|
||||||
|
TokenType.Pipe -> InfixOperator.BinaryOr
|
||||||
|
TokenType.Caret -> InfixOperator.BinaryExclusiveOr
|
||||||
TokenType.Equality -> InfixOperator.Equals
|
TokenType.Equality -> InfixOperator.Equals
|
||||||
TokenType.Inequality -> InfixOperator.NotEquals
|
TokenType.Inequality -> InfixOperator.NotEquals
|
||||||
TokenType.Mod -> InfixOperator.EuclideanModulo
|
TokenType.Mod -> InfixOperator.EuclideanModulo
|
||||||
@ -325,6 +331,7 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
private fun convertPrefixOperator(token: Token): PrefixOperator = when (token.type) {
|
private fun convertPrefixOperator(token: Token): PrefixOperator = when (token.type) {
|
||||||
TokenType.Plus -> PrefixOperator.UnaryPlus
|
TokenType.Plus -> PrefixOperator.UnaryPlus
|
||||||
TokenType.Minus -> PrefixOperator.UnaryMinus
|
TokenType.Minus -> PrefixOperator.UnaryMinus
|
||||||
|
TokenType.Tilde -> PrefixOperator.BinaryNot
|
||||||
else -> throw RuntimeException("Unknown Prefix Operator")
|
else -> throw RuntimeException("Unknown Prefix Operator")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,10 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
|||||||
Minus(SingleChar('-'), OperatorFamily, Promotion('-', MinusMinus)),
|
Minus(SingleChar('-'), OperatorFamily, Promotion('-', MinusMinus)),
|
||||||
Multiply(SingleChar('*'), OperatorFamily),
|
Multiply(SingleChar('*'), OperatorFamily),
|
||||||
Divide(SingleChar('/'), OperatorFamily),
|
Divide(SingleChar('/'), OperatorFamily),
|
||||||
|
Tilde(SingleChar('~'), OperatorFamily),
|
||||||
|
Ampersand(SingleChar('&'), OperatorFamily),
|
||||||
|
Pipe(SingleChar('|'), OperatorFamily),
|
||||||
|
Caret(SingleChar('^'), OperatorFamily),
|
||||||
LesserEqual(OperatorFamily),
|
LesserEqual(OperatorFamily),
|
||||||
GreaterEqual(OperatorFamily),
|
GreaterEqual(OperatorFamily),
|
||||||
Lesser(SingleChar('<'), OperatorFamily, Promotion('=', LesserEqual)),
|
Lesser(SingleChar('<'), OperatorFamily, Promotion('=', LesserEqual)),
|
||||||
|
Reference in New Issue
Block a user