aboutsummaryrefslogtreecommitdiff
path: root/neb/std/lists.py
blob: d5c18c2e72db670675f79a99a4e5ef067095c061 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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)))