evaluator: prevent double lookup when looking up value in a scope

This commit is contained in:
Alex Zenla 2023-09-05 01:09:26 -07:00
parent 7de8f8cd63
commit cc23789203
Signed by: alex
GPG Key ID: C0780728420EBFE5

View File

@ -4,11 +4,6 @@ class Scope(val parent: Scope? = null, inherits: List<Scope> = emptyList()) {
private val inherited = inherits.toMutableList() private val inherited = inherits.toMutableList()
private val variables = mutableMapOf<String, Any>() private val variables = mutableMapOf<String, Any>()
fun has(name: String): Boolean =
variables.containsKey(name) ||
(parent?.has(name) ?: false) ||
inherited.any { inherit -> inherit.has(name) }
fun define(name: String, value: Any) { fun define(name: String, value: Any) {
if (variables.containsKey(name)) { if (variables.containsKey(name)) {
throw RuntimeException("Variable '${name}' is already defined") throw RuntimeException("Variable '${name}' is already defined")
@ -17,20 +12,30 @@ class Scope(val parent: Scope? = null, inherits: List<Scope> = emptyList()) {
} }
fun value(name: String): Any { fun value(name: String): Any {
val value = valueOrNotFound(name)
if (value == NotFound) {
throw RuntimeException("Variable '${name}' not defined.")
}
return value
}
private fun valueOrNotFound(name: String): Any {
val value = variables[name] val value = variables[name]
if (value == null) { if (value == null) {
if (parent != null) { if (parent != null) {
if (parent.has(name)) { val parentMaybeFound = parent.valueOrNotFound(name)
return parent.value(name) if (parentMaybeFound != NotFound) {
return parentMaybeFound
} }
} }
for (inherit in inherited) { for (inherit in inherited) {
if (inherit.has(name)) { val inheritMaybeFound = inherit.valueOrNotFound(name)
return inherit.value(name) if (inheritMaybeFound != NotFound) {
return inheritMaybeFound
} }
} }
throw RuntimeException("Variable '${name}' not defined.") return NotFound
} }
return value return value
} }
@ -57,4 +62,6 @@ class Scope(val parent: Scope? = null, inherits: List<Scope> = emptyList()) {
internal fun inherit(scope: Scope) { internal fun inherit(scope: Scope) {
inherited.add(scope) inherited.add(scope)
} }
private object NotFound
} }