def join_fn(args: List[objects.Object]) -> objects.Object: if len(args) != 2: return wrong_number_of_args(actual=len(args), expected=2) if args[0].object_type() != ObjectType.ARRAY_OBJ: return objects.Error( f"first argument to `join` must be ARRAY, got {args[0].object_type().value}" ) if args[1].object_type() != ObjectType.STRING_OBJ: return objects.Error( f"second argument to `join` must be STRING, got {args[1].object_type().value}" ) elements = args[0].elements if len(elements) == 0: return objects.String("") if len(elements) == 1: return objects.String(str(elements[0])) max_ = len(elements) - 1 out = f"" for i, el in enumerate(elements): out += str(el) if i < max_: out += str(args[1]) return objects.String(out)
def exit_fn(args: List[objects.Object]) -> None: if len(args) not in [0, 1]: return objects.Error(f"wrong number of arguments. got={len(args)}, want=0 or 1") if len(args) == 1: if args[0].object_type() != ObjectType.INTEGER_OBJ: return objects.Error( f"argument to `exit` must be INTEGER, got {args[0].object_type().value}" ) else: sys.exit(args[0].value) else: sys.exit(0)
def int_fn(args: List[objects.Object]) -> objects.Object: if len(args) != 1: return wrong_number_of_args(actual=len(args), expected=1) src = args[0] if src.object_type() == ObjectType.INTEGER_OBJ: return src elif src.object_type() == ObjectType.STRING_OBJ: print(src) try: i = int(src.value) ix = objects.Integer(TokenType.INT) ix.value = i return ix except ValueError: return objects.Error( f"Cannot cast {src.object_type().value}({src}) to INTEGER" ) return objects.Error(f"Cannot cast {src.object_type().value}({src}) to INTEGER")
def len_fn(args: List[objects.Object]) -> objects.Object: if len(args) != 1: return wrong_number_of_args(actual=len(args), expected=1) if isinstance(args[0], objects.Array): return objects.Integer(len(args[0].elements)) elif isinstance(args[0], objects.String): return objects.Integer(len(args[0].value)) return objects.Error( f"argument to `len` not supported, got {args[0].object_type().value}" )
def split_fn(args: List[objects.Object]) -> objects.Object: if len(args) != 2: return wrong_number_of_args(actual=len(args), expected=2) string = args[0] delimiter = args[1] if not isinstance(string, objects.String): return objects.Error( f"first argument to `split` must be STRING, got {string.object_type().value}({args[0]})" ) if not isinstance(delimiter, objects.String): return objects.Error( f"second argument to `split` must be STRING, got {delimiter.object_type().value}({args[1]})" ) elements = string.value.split(delimiter.value) strElements = [objects.String(el) for el in elements] return objects.Array(strElements)
def push_fn(args: List[objects.Object]) -> objects.Object: if len(args) != 2: return wrong_number_of_args(actual=len(args), expected=2) if args[0].object_type() != ObjectType.ARRAY_OBJ: return objects.Error( f"first argument to `push` must be ARRAY, got {args[0].object_type().value}" ) arr = args[0] new_elements = list(arr.elements) new_elements.append(args[1]) return objects.Array(new_elements)
def rest_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 `rest` must be ARRAY, got {args[0].object_type().value}" ) arr = args[0] if len(arr.elements): return objects.Array(arr.elements[1:]) return objects.Array([])
def values_fn(args: List[objects.Object]) -> objects.Object: if len(args) != 1: return wrong_number_of_args(actual=len(args), expected=1) src = args[0] if src.object_type() == ObjectType.HASH_OBJ: hash_ = src elif src.object_type() == ObjectType.MODULE: if not isinstance(src, objects.Module): return objects.Error( f"argument to `values` must be HASH or MODULE, got {src.object_type().value}({src})" ) hash_ = module.attrs else: return objects.Error( f"argument to `values` must be HASH or MODULE, got {src.object_type().value}({src})" ) values = [hash_pair.value for hash_key, hash_pair in hash_.pairs.items()] return objects.Array(values)
def extend_function_env( fn: objects.Function, args: List[objects.Object] ) -> Union[objects.Environment, objects.Error]: env = objects.Environment({}, fn.env) for i, param in enumerate(fn.parameters): try: env.set(param.value, args[i]) except IndexError: return objects.Error(f"{param.value} not supplied") return env
def reverse_fn(args: List[objects.Object]) -> objects.Object: if len(args) != 1: return wrong_number_of_args(actual=len(args), expected=1) src = args[0] if src.object_type() == ObjectType.ARRAY_OBJ: reversed_elements = src.elements[::-1] return objects.Array(reversed_elements) elif src.object_type() == ObjectType.STRING_OBJ: return objects.String(src.value[::-1]) return objects.Error( f"argument to `reverse` must be ARRAY or STRING, got {src.object_type().value}" )
def wrong_number_of_args(actual, expected=1): return objects.Error(f"wrong number of arguments. got={actual}, want={expected}")
def new_error(message: str) -> objects.Error: return objects.Error(message)