Commit | Line | Data |
---|---|---|
7e823504 NF |
1 | %%% |
2 | %%% Core functions | |
3 | %%% | |
4 | ||
5 | -module(core). | |
6 | -compile(export_all). | |
7 | ||
a61ea75a NF |
8 | count([Args]) -> |
9 | case Args of | |
10 | {list, List} -> {integer, length(List)}; | |
11 | {vector, List} -> {integer, length(List)}; | |
12 | nil -> {integer, 0}; | |
13 | _ -> {error, "count called on non-sequence"} | |
14 | end; | |
15 | count([]) -> | |
16 | {error, "count called with no arguments"}; | |
17 | count(_) -> | |
18 | {error, "count expects one list argument"}. | |
19 | ||
20 | empty_q([Args]) -> | |
21 | case Args of | |
22 | {list, List} -> length(List) == 0; | |
23 | {vector, List} -> length(List) == 0; | |
24 | _ -> {error, "empty? called on non-sequence"} | |
25 | end; | |
26 | empty_q([]) -> | |
27 | {error, "empty? called with no arguments"}; | |
28 | empty_q(_) -> | |
29 | {error, "empty? expects one list argument"}. | |
30 | ||
31 | equal_q(Args) -> | |
32 | case Args of | |
33 | [nil, nil] -> true; | |
34 | [true, true] -> true; | |
35 | [false, false] -> true; | |
36 | [{integer, I}, {integer, J}] -> I == J; | |
37 | [{string, S}, {string, T}] -> S == T; | |
38 | [{keyword, K}, {keyword, J}] -> K == J; | |
39 | [{symbol, S}, {symbol, T}] -> S == T; | |
40 | [{list, L1}, {list, L2}] -> L1 == L2; | |
41 | [{vector, L1}, {vector, L2}] -> L1 == L2; | |
42 | [{list, L1}, {vector, L2}] -> L1 == L2; | |
43 | [{vector, L1}, {list, L2}] -> L1 == L2; | |
44 | [{map, M1}, {map, M2}] -> M1 == M2; | |
45 | [{closure, _C1}, {closure, _C2}] -> false; | |
46 | [{function, _F1}, {function, _F2}] -> false; | |
47 | [_A, _B] -> false; | |
48 | _ -> {error, "equal? expects two arguments"} | |
49 | end. | |
7e823504 | 50 | |
583a62df | 51 | int_op(F, [A0,A1]) -> |
7e823504 NF |
52 | case A0 of |
53 | {integer, I0} -> | |
54 | case A1 of | |
55 | {integer, I1} -> | |
a61ea75a | 56 | {integer, F(I0, I1)}; |
7e823504 NF |
57 | _ -> {error, "second argument must be an integer"} |
58 | end; | |
59 | _ -> {error, "first argument must be an integer"} | |
60 | end; | |
61 | int_op(_F, _L) -> | |
62 | {error, "must have two arguments"}. | |
63 | ||
64 | int_add(Args) -> | |
a61ea75a | 65 | int_op(fun(I, J) -> I + J end, Args). |
7e823504 NF |
66 | |
67 | int_sub(Args) -> | |
a61ea75a | 68 | int_op(fun(I, J) -> I - J end, Args). |
7e823504 NF |
69 | |
70 | int_mul(Args) -> | |
a61ea75a | 71 | int_op(fun(I, J) -> I * J end, Args). |
7e823504 NF |
72 | |
73 | int_div(Args) -> | |
a61ea75a NF |
74 | int_op(fun(I, J) -> I div J end, Args). |
75 | ||
76 | bool_op(F, [A0,A1]) -> | |
77 | case A0 of | |
78 | {integer, I0} -> | |
79 | case A1 of | |
80 | {integer, I1} -> | |
81 | % the true or false is our return value | |
82 | F(I0, I1); | |
83 | _ -> {error, "second argument must be an integer"} | |
84 | end; | |
85 | _ -> {error, "first argument must be an integer"} | |
86 | end; | |
87 | bool_op(_F, _L) -> | |
88 | {error, "must have two arguments"}. | |
89 | ||
90 | bool_lt(Args) -> | |
91 | bool_op(fun(I, J) -> I < J end, Args). | |
92 | ||
93 | bool_lte(Args) -> | |
94 | bool_op(fun(I, J) -> I =< J end, Args). | |
95 | ||
96 | bool_gt(Args) -> | |
97 | bool_op(fun(I, J) -> I > J end, Args). | |
98 | ||
99 | bool_gte(Args) -> | |
100 | bool_op(fun(I, J) -> I >= J end, Args). | |
101 | ||
102 | pr_str(Args) -> | |
103 | {string, printer:pr_list(Args, "", "", " ", true)}. | |
104 | ||
105 | str(Args) -> | |
106 | {string, printer:pr_list(Args, "", "", "", false)}. | |
107 | ||
108 | prn(Args) -> | |
109 | io:format("~s~n", [printer:pr_list(Args, "", "", " ", true)]), | |
110 | nil. | |
111 | ||
112 | println(Args) -> | |
113 | io:format("~s~n", [printer:pr_list(Args, "", "", " ", false)]), | |
114 | nil. | |
7e823504 NF |
115 | |
116 | ns() -> | |
a61ea75a NF |
117 | Builtins = #{ |
118 | "*" => fun int_mul/1, | |
119 | "+" => fun int_add/1, | |
120 | "-" => fun int_sub/1, | |
121 | "/" => fun int_div/1, | |
122 | "<" => fun bool_lt/1, | |
123 | "<=" => fun bool_lte/1, | |
124 | "=" => fun equal_q/1, | |
125 | ">" => fun bool_gt/1, | |
126 | ">=" => fun bool_gte/1, | |
127 | "count" => fun count/1, | |
128 | "empty?" => fun empty_q/1, | |
129 | "list" => fun types:list/1, | |
130 | "list?" => fun types:list_p/1, | |
131 | "pr-str" => fun pr_str/1, | |
132 | "println" => fun println/1, | |
133 | "prn" => fun prn/1, | |
134 | "str" => fun str/1 | |
135 | }, | |
136 | SetEnv = fun(K, V, AccIn) -> | |
137 | env:set(AccIn, {symbol, K}, types:func(V)) | |
138 | end, | |
139 | maps:fold(SetEnv, env:new(undefined), Builtins). |