Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

language: euclidean modulo and remainder infix operators #3

Merged
merged 1 commit into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ast/src/main/ast/pork.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ types:
- name: NotEquals
values:
token: "!="
- name: EuclideanModulo
values:
token: "mod"
- name: Remainder
values:
token: "rem"
InfixOperation:
parent: Expression
values:
Expand Down
4 changes: 3 additions & 1 deletion ast/src/main/kotlin/gay/pizza/pork/ast/InfixOperator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ enum class InfixOperator(val token: String) {
Multiply("*"),
Divide("/"),
Equals("=="),
NotEquals("!=")
NotEquals("!="),
EuclideanModulo("mod"),
Remainder("rem")
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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") }
)
}

Expand All @@ -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") }
)
}

Expand All @@ -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 }
)
}

Expand All @@ -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 }
)
}

Expand All @@ -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")
}
}
Expand Down
6 changes: 5 additions & 1 deletion parser/src/main/kotlin/gay/pizza/pork/parser/Parser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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")
}

Expand Down
2 changes: 2 additions & 0 deletions parser/src/main/kotlin/gay/pizza/pork/parser/TokenType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down