Added the Interpreter class

main
oabrivard 2 years ago
parent 8aa86a34ce
commit 35974645a4

@ -0,0 +1,111 @@
package fr.celticinfo.lox
import fr.celticinfo.lox.TokenType.*
class Interpreter: ExprVisitor<Any?>{
override fun visitBinary(binary: Binary): Any? {
val left = evaluate(binary.left)
val right = evaluate(binary.right)
return when (binary.operator.type) {
MINUS -> {
checkNumberOperands(binary.operator, left, right)
left as Double - right as Double
}
SLASH -> {
checkNumberOperands(binary.operator, left, right)
if (right == 0.0) {
throw RuntimeError(binary.operator, "Division by zero")
}
left as Double / right as Double
}
STAR -> {
checkNumberOperands(binary.operator, left, right)
left as Double * right as Double
}
PLUS -> {
if (left is Double && right is Double) {
left + right
} else if (left is String && right is String) {
left + right
} else {
throw RuntimeError(binary.operator, "Operands must be two numbers or two strings")
}
}
GREATER -> {
checkNumberOperands(binary.operator, left, right)
left as Double > right as Double
}
GREATER_EQUAL -> {
checkNumberOperands(binary.operator, left, right)
left as Double >= right as Double
}
LESS -> {
checkNumberOperands(binary.operator, left, right)
(left as Double) < right as Double
}
LESS_EQUAL -> {
checkNumberOperands(binary.operator, left, right)
left as Double <= right as Double
}
BANG_EQUAL -> return !isEqual(left, right)
EQUAL_EQUAL -> return isEqual(left, right)
else -> null
}
}
override fun visitGrouping(grouping: Grouping): Any? {
return evaluate(grouping.expression)
}
override fun visitLiteral(literal: Literal): Any? {
return literal.value
}
override fun visitUnary(unary: Unary): Any? {
val right = evaluate(unary.right)
return when (unary.operator.type) {
MINUS -> {
checkNumberOperand(unary.operator, right)
-(right as Double)
}
BANG -> !isTruthy(right)
else -> null
}
}
private fun isTruthy(obj: Any?): Boolean {
return when (obj) {
null -> false
is Boolean -> obj
else -> true
}
}
private fun evaluate(expr: Expr): Any? {
return expr.accept(this)
}
private fun isEqual(left: Any?, right: Any?): Boolean {
return if (left == null && right == null) {
true
} else if (left == null) {
false
} else {
left == right
}
}
private fun checkNumberOperand(operator: Token, right: Any?) {
if (right !is Double) {
throw RuntimeError(operator, "Operand must be a number")
}
}
private fun checkNumberOperands(operator: Token, left: Any?, right: Any?) {
if (left !is Double || right !is Double) {
throw RuntimeError(operator, "Operands must be numbers")
}
}
}

@ -0,0 +1,5 @@
package fr.celticinfo.lox
class RuntimeError(val token: Token, message: String) : RuntimeException(message) {
}
Loading…
Cancel
Save