aboutsummaryrefslogtreecommitdiff
path: root/neb/std/functools.py
blob: 8ef5630cbd6b97be1099fdffd06a8ea56e9dca85 (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
from .. import TypeEnum, Environment, Arg, Builtin, Function, evaluate, InterpretPanic, NebSyntax
from ..structs import *

FUNCTOOLS = Environment()

def interpretFilter(symbol, args, env, ns):
    func = args[0]
    if not isinstance(func, Function):
        raise InterpretPanic(symbol, "requires a :func as its first argument", func)
    lst = args[1]
    out = []
    for arg in lst.args:
        ev = func.call(Expr([func, arg]), env, ns)
        if not isinstance(ev, Bool):
            raise InterpretPanic(symbol, "function must return :bool", ev)
        if ev.value:
            out.append(arg)
    return List(out)

FUNCTOOLS.register("filter", Builtin("filter", interpretFilter, [Arg("func", TypeEnum.ANY), Arg("list", TypeEnum.LIST)], return_type=Type(":list")))

def interpretMap(symbol, args, env, ns):
    func = args[0]
    if not isinstance(func, Function):
        raise InterpretPanic(symbol, "requires a :func as its first argument", func)
    lst = args[1]
    if not isinstance(lst, List):
        raise InterpretPanic(symbol, "requires a :list as its second argument", lst)
    out = []
    for arg in lst.args:
        ev = func.call(Expr([func, arg]), env, ns)
        out.append(ev)
    return List(out)

FUNCTOOLS.register("map", Builtin("map", interpretMap, [Arg("func", TypeEnum.ANY), Arg("list", TypeEnum.LIST)], return_type=Type(":list")))

# TODO I think this is wrong
def interpretApply(symbol, args, env, ns):
    func = args[0]
    if not isinstance(func, Function):
        raise InterpretPanic(symbol, "requires a symbol as its first argument", func)
    return func.call(Expr([func] + args[1].args), env, ns)

FUNCTOOLS.register("apply", Builtin("apply", interpretApply, [Arg("func", TypeEnum.ANY), Arg("list", TypeEnum.LIST)]))

def interpretReduce(symbol, args, env, ns):
    func = args[0]
    if not (isinstance(func, Function) or isinstance(func, NebSyntax)):
        raise InterpretPanic(symbol, "requires a symbol as its first argument", func)

    ret = args[2]  # this is the accumulator
    for arg in args[1].args:
        ret = func.call(Expr([func, ret, arg]), env, ns)
    return ret

FUNCTOOLS.register("reduce", Builtin("reduce", interpretReduce, [Arg("func", TypeEnum.ANY), Arg("list", TypeEnum.LIST), Arg("accum", TypeEnum.ANY)], return_type=Type(":list")))