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 return True
def evaluate_array_index_expression(array: objects.Object, index: objects.Object) -> objects.Object: idx = index.value if idx < 0 or idx > len(array.elements) - 1: return objects.Null() return array.elements[idx]
def evaluate_bang_operator_expression(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 evaluate_hash_index_expression(hash_obj: objects.Object, index: objects.Object) -> objects.Object: if not isinstance(index, objects.Hashable): return new_error(f"unusable as hash key: {index.object_type().value}") pair = hash_obj.pairs.get(index.hash_key(), None) if pair is None: return objects.Null() return pair.value
def evaluate_if_expression(expression: ast.IfExpression, env: objects.Environment) -> objects.Object: condition = evaluate(expression.condition, env) if is_error(condition): return condition if is_truthy(condition): return evaluate(expression.consequence, env) if expression.alternative is not None: return evaluate(expression.alternative, env) return objects.Null()
def last_fn(args: List[objects.Object]) -> objects.Object: if len(args) != 1: return wrong_number_of_args(actual=len(args), expected=1) if args[0].object_type() != ObjectType.ARRAY_OBJ: return objects.Error( f"argument to `last` must be ARRAY, got {args[0].object_type().value}" ) arr = args[0] if len(arr.elements): return arr.elements[-1] return objects.Null()
def puts_fn(args: List[objects.Object]) -> objects.Object: for arg in args: print(str(arg)) return objects.Null()