mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-02 12:50:55 +00:00
language: euclidean modulo and remainder infix operators (#3)
This commit is contained in:
parent
03c278f5b1
commit
0024a8b141
@ -64,6 +64,12 @@ types:
|
||||
- name: NotEquals
|
||||
values:
|
||||
token: "!="
|
||||
- name: EuclideanModulo
|
||||
values:
|
||||
token: "mod"
|
||||
- name: Remainder
|
||||
values:
|
||||
token: "rem"
|
||||
InfixOperation:
|
||||
parent: Expression
|
||||
values:
|
||||
|
@ -12,5 +12,7 @@ enum class InfixOperator(val token: String) {
|
||||
Multiply("*"),
|
||||
Divide("/"),
|
||||
Equals("=="),
|
||||
NotEquals("!=")
|
||||
NotEquals("!="),
|
||||
EuclideanModulo("mod"),
|
||||
Remainder("rem")
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package gay.pizza.pork.evaluator
|
||||
|
||||
import gay.pizza.pork.ast.*
|
||||
import kotlin.math.abs
|
||||
|
||||
class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
private var currentScope: Scope = root
|
||||
@ -105,7 +106,9 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
add = { a, b -> a + b },
|
||||
subtract = { a, b -> a - b },
|
||||
multiply = { a, b -> a * b },
|
||||
divide = { a, b -> a / b }
|
||||
divide = { a, b -> a / b },
|
||||
euclideanModulo = { a, b -> throw RuntimeException("Can't perform integer modulo between floating point types") },
|
||||
remainder = { a, b -> throw RuntimeException("Can't perform integer remainder between floating point types") }
|
||||
)
|
||||
}
|
||||
|
||||
@ -118,7 +121,9 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
add = { a, b -> a + b },
|
||||
subtract = { a, b -> a - b },
|
||||
multiply = { a, b -> a * b },
|
||||
divide = { a, b -> a / b }
|
||||
divide = { a, b -> a / b },
|
||||
euclideanModulo = { a, b -> throw RuntimeException("Can't perform integer modulo between floating point types") },
|
||||
remainder = { a, b -> throw RuntimeException("Can't perform integer remainder between floating point types") }
|
||||
)
|
||||
}
|
||||
|
||||
@ -131,7 +136,9 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
add = { a, b -> a + b },
|
||||
subtract = { 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 } },
|
||||
remainder = { x, d -> x % d }
|
||||
)
|
||||
}
|
||||
|
||||
@ -144,7 +151,9 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
add = { a, b -> a + b },
|
||||
subtract = { 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 } },
|
||||
remainder = { x, d -> x % d }
|
||||
)
|
||||
}
|
||||
|
||||
@ -159,13 +168,17 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
add: (T, T) -> T,
|
||||
subtract: (T, T) -> T,
|
||||
multiply: (T, T) -> T,
|
||||
divide: (T, T) -> T
|
||||
divide: (T, T) -> T,
|
||||
euclideanModulo: (T, T) -> T,
|
||||
remainder: (T, T) -> T
|
||||
): T {
|
||||
return when (op) {
|
||||
InfixOperator.Plus -> add(convert(left), convert(right))
|
||||
InfixOperator.Minus -> subtract(convert(left), convert(right))
|
||||
InfixOperator.Multiply -> multiply(convert(left), convert(right))
|
||||
InfixOperator.Divide -> divide(convert(left), convert(right))
|
||||
InfixOperator.EuclideanModulo -> euclideanModulo(convert(left), convert(right))
|
||||
InfixOperator.Remainder -> remainder(convert(left), convert(right))
|
||||
else -> throw RuntimeException("Unable to handle operation $op")
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +167,9 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
||||
TokenType.Multiply,
|
||||
TokenType.Divide,
|
||||
TokenType.Equality,
|
||||
TokenType.Inequality
|
||||
TokenType.Inequality,
|
||||
TokenType.Mod,
|
||||
TokenType.Rem
|
||||
)
|
||||
) {
|
||||
within {
|
||||
@ -264,6 +266,8 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
||||
TokenType.Divide -> InfixOperator.Divide
|
||||
TokenType.Equality -> InfixOperator.Equals
|
||||
TokenType.Inequality -> InfixOperator.NotEquals
|
||||
TokenType.Mod -> InfixOperator.EuclideanModulo
|
||||
TokenType.Rem -> InfixOperator.Remainder
|
||||
else -> throw RuntimeException("Unknown Infix Operator")
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,8 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
||||
LeftParentheses(SingleChar('(')),
|
||||
RightParentheses(SingleChar(')')),
|
||||
Negation(SingleChar('!'), Promotion('=', Inequality), OperatorFamily),
|
||||
Mod(Keyword("mod"), OperatorFamily),
|
||||
Rem(Keyword("rem"), OperatorFamily),
|
||||
Comma(SingleChar(',')),
|
||||
Period(SingleChar('.')),
|
||||
False(Keyword("false"), KeywordFamily),
|
||||
|
Loading…
Reference in New Issue
Block a user