def is_truthy(obj: objects.Object) -> bool: if obj is objects.Null(): return False elif obj is objects.Boolean(True): return True elif obj is objects.Boolean(False): return False else: return True
def eval_array_index_exp(array: objects.Array, index: objects.Integer) -> objects.Object: idx = index.value max_len = len(array.elements) - 1 if idx < 0 or idx > max_len: return objects.Null() return array.elements[idx]
def eval_bang_operator_exp(right: objects.Object) -> objects.Object: if right is objects.Boolean(True): return objects.Boolean(False) elif right is objects.Boolean(False): return objects.Boolean(True) elif right is objects.Null(): return objects.Boolean(True) else: return objects.Boolean(False)
def eval_dict_index_exp(dictionary: objects.Dictionary, index: objects.Object) -> objects.Object: if not isinstance(index, objects.Hashable): return objects.Error(f"unusable as dictionary key: {index.tp().value}") pair = dictionary.pairs.get(index.hashkey(), None) if pair is None: return objects.Null() return pair.value
def eval_if_exp(exp: ast.IfExpression, env: objects.Environment) -> typing.Optional[objects.Object]: condition = evaluate(exp.condition, env) if is_error(condition) or condition is None: return condition if is_truthy(condition): return evaluate(exp.consequence, env) elif hasattr(exp, "alternative"): return evaluate(exp.alternative, env) else: return objects.Null()
def _test_null_object(self, obj: objects.Object): if obj is not objects.Null(): self.fail(f"Object is not NULL. Got {obj}.")