from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic, NebSyntax, MultiFunction from ..structs import * import random LISTS = Environment() def interpretListLength(symbol, args, env, ns): return Int(len(args[0].args)) length_func = Builtin("length", interpretListLength, [Arg("arg", TypeEnum.LIST)], return_type=Type(":int")) length_multi = MultiFunction("length") length_multi.register(length_func) LISTS.register("length", length_multi) def interpretFirst(symbol, args, env, ns): if len(args[0].args) == 0: raise InterpretPanic(symbol, "list is empty") return evaluate(args[0].args[0], env, ns) first_func = Builtin("first", interpretFirst, [Arg("arg", TypeEnum.LIST)]) first_multi = MultiFunction("first") first_multi.register(first_func) LISTS.register("first", first_multi) def interpretRest(symbol, args, env, ns): # TODO do we know it's not evaluated? return List(args[0].args[1:]) # we don't evaluate the remainder of the list rest_func = Builtin("rest", interpretRest, [Arg("arg", TypeEnum.LIST)], return_type=Type(":[]")) rest_multi = MultiFunction("rest") rest_multi.register(rest_func) LISTS.register("rest", rest_multi) def interpretListReverse(symbol, args, env, ns): new_args = args[0].args[:] # make a copy of the args new_args.reverse() return List(new_args) reverse_func = Builtin("reverse", interpretListReverse, [Arg("list", TypeEnum.LIST)], return_type=Type(":[]")) reverse_multi = MultiFunction("reverse") reverse_multi.register(reverse_func) LISTS.register("reverse", reverse_multi) def interpretEmpty(symbol, args, env, ns): return Bool(len(args[0].args) == 0) empty_func = Builtin("empty?", interpretEmpty, [Arg("list", TypeEnum.LIST)], return_type=Type(":bool")) empty_multi = MultiFunction("empty") empty_multi.register(empty_func) LISTS.register("empty?", empty_multi) def interpretShuf(symbol, args, env, ns): items = args[0].args[:] random.shuffle(items) return List(items) shuf_func = Builtin("shuf", interpretShuf, [Arg("list", TypeEnum.LIST)], return_type=Type(":[]")) shuf_multi = MultiFunction("shuf") shuf_multi.register(shuf_func) LISTS.register("shuf", shuf_multi) def interpretIn(symbol, args, env, ns): target = args[0] lst = args[1] for arg in lst.args: if type(arg) == type(target) and arg.value == target.value: return Bool(True) return Bool(False) in_target_arg = Arg("target", TypeEnum.LITERAL) in_list_arg = Arg("list", TypeEnum.LIST) in_func = Builtin("in?", interpretIn, [in_target_arg, in_list_arg], return_type=Type(":bool")) in_multi = MultiFunction("in?") in_multi.register(in_func) LISTS.register("in?", in_multi) def interpretLast(symbol, args, env, ns): if len(args[0].args) == 0: raise InterpretPanic(symbol, "list is empty") return evaluate(args[0].args[-1], env, ns) last_func = Builtin("last", interpretLast, [Arg("list", TypeEnum.LIST)]) last_multi = MultiFunction("last") last_multi.register(last_func) LISTS.register("last", last_multi) def interpretSlice(symbol, args, env, ns): lst = args[0] idx = args[1] if len(args) == 2: return List(lst.args[idx.value - 1:]) length = args[2] diff = idx.value - 1 + length.value return List(lst.args[idx.value - 1:diff]) slice_list_arg = Arg("list", TypeEnum.LIST) slice_idx_arg = Arg("idx", TypeEnum.INT) slice_length_arg = Arg("length", TypeEnum.INT) slice_nolength_func = Builtin("slice", interpretSlice, [slice_list_arg, slice_idx_arg], return_type=Type(":[]")) slice_length_func = Builtin("slice", interpretSlice, [slice_list_arg, slice_idx_arg, slice_length_arg], return_type=Type(":[]")) slice_multi = MultiFunction("slice") slice_multi.register(slice_nolength_func) slice_multi.register(slice_length_func) LISTS.register("slice", slice_multi) def interpretAppend(symbol, args, env, ns): lst = args[0] val = args[1] items = lst.args[:] return List(items + [val]) append_func = Builtin("append", interpretAppend, [Arg("list", TypeEnum.LIST), Arg("item", TypeEnum.ANY)], return_type=Type(":[]")) append_multi = MultiFunction("append") append_multi.register(append_func) LISTS.register("append", append_multi) # TODO: this is actually for records/structs/whatever they're called def interpretRemove(symbol, args, env, ns): lst = args[0] key = args[1] out = [] for arg in lst.args: if arg.args[0].value != key.value: out.append(arg) return List(out) remove_func = Builtin("remove", interpretRemove, [Arg("list", TypeEnum.LIST), Arg("key", TypeEnum.ANY)], return_type=Type(":[]")) remove_multi = MultiFunction("remove") remove_multi.register(remove_func) LISTS.register("remove", remove_multi) def interpretZip(symbol, args, env, ns): z1 = args[0] z2 = args[1] if len(z1.args) != len(z2.args): raise InterpretPanic(symbol, "requires two :lists of the same size") out = [] for idx in range(len(z1.args)): f = z1.args[idx] s = z2.args[idx] out.append(List([f, s])) return List(out) zip_arg = Arg("list", TypeEnum.LIST) zip_func = Builtin("zip", interpretZip, [zip_arg, zip_arg], return_type=Type(":[]")) zip_multi = MultiFunction("zip") zip_multi.register(zip_func) LISTS.register("zip", zip_multi) def interpretList(symbol, args, env, ns): return List(args) list_func = Builtin("list", interpretList, [], Arg("item", TypeEnum.ANY), Type(":[]")) list_multi = MultiFunction("list") list_multi.register(list_func) LISTS.register("list", list_multi) ''' def interpretSortNumbers(symbol, args, env, ns): items = [] for arg in args[0].args: if not isinstance(arg, Int) and not isinstance(arg, Float): raise InterpretPanic(symbol, "requires all :numbers", arg) items.append(arg.value) items.sort() out = [] for item in items: if isinstance(item, int): out.append(Int(item)) else: out.append(Float(item)) return List(out) LISTS.register("sort-numbers", Builtin("sort-numbers", interpretSortNumbers, [Arg("list", TypeEnum.LIST)], return_type=Type(":list"))) ''' def interpretPrepend(symbol, args, env, ns): lst = args[0] val = args[1] items = lst.args[:] return List([val] + items) prepend_func = Builtin("prepend", interpretPrepend, [Arg("list", TypeEnum.LIST), Arg("item", TypeEnum.ANY)], return_type=Type(":[]")) prepend_multi = MultiFunction("prepend") prepend_multi.register(prepend_func) LISTS.register("prepend", prepend_multi) def interpretListMost(symbol, args, env, ns): return List(args[0].args[:-1]) most_func = Builtin("most", interpretListMost, [Arg("list", TypeEnum.LIST)], return_type=Type(":[]")) most_multi = MultiFunction("most") most_multi.register(most_func) LISTS.register("most", most_multi)