diff options
| author | mryouse | 2022-06-21 01:49:29 +0000 |
|---|---|---|
| committer | mryouse | 2022-06-21 01:49:29 +0000 |
| commit | 776fe3193b515c028b5ac69326baed51d760d32f (patch) | |
| tree | db111c3fe7a20143b2f058259f86dbbecae4cbd6 /neb/std/lists.py | |
| parent | b1550660adaca68bb38541aed371e36b7000e124 (diff) | |
refactor: break stdlib into several files
Diffstat (limited to 'neb/std/lists.py')
| -rw-r--r-- | neb/std/lists.py | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/neb/std/lists.py b/neb/std/lists.py new file mode 100644 index 0000000..d5c18c2 --- /dev/null +++ b/neb/std/lists.py @@ -0,0 +1,116 @@ +from .. import TypeEnum, Environment, Arg, Builtin, evaluate +from ..structs import * +import random + +LISTS = Environment() + +def interpretListLength(symbol, args, env, ns): + return Int(len(args[0].args)) + +LISTS.register("list-length", Builtin(interpretListLength, [Arg("arg", TypeEnum.LIST)])) + +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) + +LISTS.register("first", Builtin(interpretFirst, [Arg("arg", TypeEnum.LIST, )])) + +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 + +LISTS.register("rest", Builtin(interpretRest, [Arg("arg", TypeEnum.LIST)])) + +def interpretListReverse(symbol, args, env, ns): + new_args = args[0].args[:] # make a copy of the args + new_args.reverse() + return List(new_args) + +LISTS.register("list-reverse", Builtin(interpretListReverse, [Arg("list", TypeEnum.LIST)])) + +def interpretEmpty(symbol, args, env, ns): + return Bool(len(args[0].args) == 0) + +LISTS.register("empty?", Builtin(interpretEmpty, [Arg("list", TypeEnum.LIST)])) + +def interpretShuf(symbol, args, env, ns): + items = args[0].args[:] + random.shuffle(items) + return List(items) + +LISTS.register("shuf", Builtin(interpretShuf, [Arg("list", TypeEnum.LIST)])) + +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) +LISTS.register("in?", Builtin(interpretIn, [in_target_arg, in_list_arg])) + +def interpretLast(symbol, args, env, ns): + if len(args[0].args) == 0: + raise InterpretPanic("List is empty") + return evaluate(args[0].args[-1], env, ns) + +LISTS.register("last", Builtin(interpretLast, [Arg("list", TypeEnum.LIST)])) + +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, optional=True) +LISTS.register("slice", Builtin(interpretSlice, [slice_list_arg, slice_idx_arg, slice_length_arg])) + +def interpretAppend(symbol, args, env, ns): + lst = args[0] + val = args[1] + items = lst.args[:] + return List(items + [val]) + +LISTS.register("append", Builtin(interpretAppend, [Arg("list", TypeEnum.LIST), Arg("item", TypeEnum.ANY)])) + +# 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) + +LISTS.register("remove", Builtin(interpretRemove, [Arg("list", TypeEnum.LIST), Arg("key", TypeEnum.ANY)])) + +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) +LISTS.register("zip", Builtin(interpretZip, [zip_arg, zip_arg])) + +def interpretList(symbol, args, env, ns): + return List(args) + +LISTS.register("list", Builtin(interpretList, [], Arg("item", TypeEnum.ANY))) + |
