aboutsummaryrefslogtreecommitdiff
path: root/neb/std/lists.py
diff options
context:
space:
mode:
authormryouse2022-06-21 01:49:29 +0000
committermryouse2022-06-21 01:49:29 +0000
commit776fe3193b515c028b5ac69326baed51d760d32f (patch)
treedb111c3fe7a20143b2f058259f86dbbecae4cbd6 /neb/std/lists.py
parentb1550660adaca68bb38541aed371e36b7000e124 (diff)
refactor: break stdlib into several files
Diffstat (limited to 'neb/std/lists.py')
-rw-r--r--neb/std/lists.py116
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)))
+