Matlab: fix real matlab issues, , add conj.
[jackhill/mal.git] / matlab / core.m
CommitLineData
d6624158
JM
1classdef core
2 methods(Static)
b550d8b7 3 function ret = throw(obj)
47699629
JM
4 ret = type_utils.nil;
5 if exist('OCTAVE_VERSION', 'builtin') ~= 0
6 % Until Octave has MException objects, we need to
7 % store the error object globally to be able to pass
8 % it to the error handler.
9 global error_object;
10 error_object = obj;
11 exc = struct('identifier', 'MalException:object',...
12 'message', 'MalException');
13 rethrow(exc);
14 else
15 throw(types.MalException(obj));
16 end
b550d8b7
JM
17 end
18
6d12affa
JM
19 function str = pr_str(varargin)
20 strs = cellfun(@(s) printer.pr_str(s,true), varargin, ...
21 'UniformOutput', false);
22 str = strjoin(strs, ' ');
23 end
24 function str = do_str(varargin)
25 strs = cellfun(@(s) printer.pr_str(s,false), varargin, ...
26 'UniformOutput', false);
27 str = strjoin(strs, '');
28 end
29 function ret = prn(varargin)
30 strs = cellfun(@(s) printer.pr_str(s,true), varargin, ...
31 'UniformOutput', false);
32 fprintf('%s\n', strjoin(strs, ' '));
47699629 33 ret = type_utils.nil;
6d12affa
JM
34 end
35 function ret = println(varargin)
36 strs = cellfun(@(s) printer.pr_str(s,false), varargin, ...
37 'UniformOutput', false);
38 fprintf('%s\n', strjoin(strs, ' '));
47699629 39 ret = type_utils.nil;
6d12affa
JM
40 end
41
7f567f36
JM
42 function ret = time_ms()
43 secs = now-repmat(datenum('1970-1-1 00:00:00'),size(now));
44 ret = floor(secs.*repmat(24*3600.0*1000,size(now)));
45 end
46
6a572dff
JM
47 function new_hm = assoc(hm, varargin)
48 new_hm = clone(hm);
49 for i=1:2:length(varargin)
50 new_hm.set(varargin{i}, varargin{i+1});
51 end
52 end
53
54 function new_hm = dissoc(hm, varargin)
55 new_hm = clone(hm);
56 ks = intersect(hm.keys(),varargin);
47699629
JM
57 if exist('OCTAVE_VERSION', 'builtin') ~= 0
58 new_hm.data.remove(ks);
59 else
60 remove(new_hm.data, ks);
61 end
6a572dff
JM
62 end
63
64 function ret = get(hm, key)
47699629
JM
65 if isa(hm, 'types.Nil')
66 ret = type_utils.nil;
d5a3eb94
JM
67 elseif hm.data.isKey(key)
68 ret = hm.data(key);
6a572dff 69 else
d5a3eb94 70 ret = type_utils.nil;
6a572dff
JM
71 end
72 end
73
74 function ret = keys(hm)
75 ks = hm.keys();
76 ret = types.List(ks{:});
77 end
78
79 function ret = vals(hm)
80 vs = hm.values();
81 ret = types.List(vs{:});
82 end
83
84 function ret = cons(a, seq)
85 cella = [{a}, seq.data];
86 ret = types.List(cella{:});
87 end
88
c3023f26
JM
89 function ret = concat(varargin)
90 if nargin == 0
6a572dff 91 cella = {};
c3023f26 92 else
6a572dff
JM
93 cells = cellfun(@(x) x.data, varargin, ...
94 'UniformOutput', false);
95 cella = cat(2,cells{:});
c3023f26 96 end
6a572dff 97 ret = types.List(cella{:});
c3023f26
JM
98 end
99
c4033aab 100 function ret = first(seq)
d5a3eb94
JM
101 if isa(seq, 'types.Nil')
102 ret = type_utils.nil;
103 elseif length(seq) < 1
47699629 104 ret = type_utils.nil;
c4033aab 105 else
6a572dff 106 ret = seq.get(1);
c4033aab
JM
107 end
108 end
109
6a572dff 110 function ret = rest(seq)
d5a3eb94
JM
111 if isa(seq, 'types.Nil')
112 ret = types.List();
113 else
114 cella = seq.data(2:end);
115 ret = types.List(cella{:});
116 end
6a572dff
JM
117 end
118
c4033aab
JM
119 function ret = nth(seq, idx)
120 if idx+1 > length(seq)
121 throw(MException('Range:nth', ...
122 'nth: index out of range'))
123 end
6a572dff 124 ret = seq.get(idx+1);
c4033aab
JM
125 end
126
b550d8b7
JM
127 function ret = apply(varargin)
128 f = varargin{1};
129 if isa(f, 'types.Function')
130 f = f.fn;
131 end
132 first_args = varargin(2:end-1);
6a572dff 133 rest_args = varargin{end}.data;
b550d8b7
JM
134 args = [first_args rest_args];
135 ret = f(args{:});
136 end
137
138 function ret = map(f, lst)
139 if isa(f, 'types.Function')
140 f = f.fn;
141 end
6a572dff
JM
142 cells = cellfun(@(x) f(x), lst.data, 'UniformOutput', false);
143 ret = types.List(cells{:});
b550d8b7
JM
144 end
145
425233e3
JM
146 function ret = conj(varargin)
147 seq = varargin{1};
148 args = varargin(2:end);
149 if type_utils.list_Q(seq)
150 cella = [fliplr(args), seq.data];
151 ret = types.List(cella{:});
152 else
153 cella = [seq.data, args];
154 ret = types.Vector(cella{:});
155 end
156 end
157
53942f88
JM
158 function new_obj = with_meta(obj, meta)
159 new_obj = clone(obj);
160 new_obj.meta = meta;
161 end
162
163 function meta = meta(obj)
164 switch class(obj)
165 case {'types.List', 'types.Vector',
166 'types.HashMap', 'types.Function'}
167 meta = obj.meta;
168 otherwise
47699629 169 meta = type_utils.nil;
53942f88
JM
170 end
171 end
172
173 function ret = reset_BANG(atm, val)
174 atm.val = val;
175 ret = val;
176 end
177
178 function ret = swap_BANG(atm, f, varargin)
179 args = [{atm.val} varargin];
180 if isa(f, 'types.Function')
181 f = f.fn;
182 end
183 atm.val = f(args{:});
184 ret = atm.val;
185 end
186
d6624158 187 function n = ns()
47699629
JM
188 if exist('OCTAVE_VERSION', 'builtin') ~= 0
189 n = Dict();
190 else
191 n = containers.Map();
192 end
193 n('=') = @(a,b) type_utils.equal(a,b);
194 n('throw') = @(a) core.throw(a);
b550d8b7
JM
195 n('nil?') = @(a) isa(a, 'types.Nil');
196 n('true?') = @(a) isa(a, 'logical') && a == true;
197 n('false?') = @(a) isa(a, 'logical') && a == false;
198 n('symbol') = @(a) types.Symbol(a);
199 n('symbol?') = @(a) isa(a, 'types.Symbol');
47699629
JM
200 n('keyword') = @(a) type_utils.keyword(a);
201 n('keyword?') = @(a) type_utils.keyword_Q(a);
202
203 n('pr-str') = @(varargin) core.pr_str(varargin{:});
204 n('str') = @(varargin) core.do_str(varargin{:});
205 n('prn') = @(varargin) core.prn(varargin{:});
206 n('println') = @(varargin) core.println(varargin{:});
207 n('read-string') = @(a) reader.read_str(a);
b550d8b7 208 n('readline') = @(p) input(p, 's');
47699629 209 n('slurp') = @(a) fileread(a);
9831bce7 210
d6624158
JM
211 n('<') = @(a,b) a<b;
212 n('<=') = @(a,b) a<=b;
213 n('>') = @(a,b) a>b;
214 n('>=') = @(a,b) a>=b;
6d12affa
JM
215 n('+') = @(a,b) a+b;
216 n('-') = @(a,b) a-b;
217 n('*') = @(a,b) a*b;
218 n('/') = @(a,b) floor(a/b);
47699629 219 n('time-ms') = @() core.time_ms();
d6624158 220
6a572dff 221 n('list') = @(varargin) types.List(varargin{:});
47699629 222 n('list?') = @(a) type_utils.list_Q(a);
6a572dff 223 n('vector') = @(varargin) types.Vector(varargin{:});
47699629 224 n('vector?') = @(a) type_utils.vector_Q(a);
6a572dff 225 n('hash-map') = @(varargin) types.HashMap(varargin{:});
47699629
JM
226 n('map?') = @(a) type_utils.hash_map_Q(a);
227 n('assoc') = @(varargin) core.assoc(varargin{:});
228 n('dissoc') = @(varargin) core.dissoc(varargin{:});
229 n('get') = @(a,b) core.get(a,b);
6a572dff 230 n('contains?') = @(a,b) a.data.isKey(b);
47699629
JM
231 n('keys') = @(a) core.keys(a);
232 n('vals') = @(a) core.vals(a);
233
234 n('sequential?') = @(a) type_utils.sequential_Q(a);
235 n('cons') = @(a,b) core.cons(a,b);
236 n('concat') = @(varargin) core.concat(varargin{:});
237 n('nth') = @(a,b) core.nth(a,b);
238 n('first') = @(a) core.first(a);
239 n('rest') = @(a) core.rest(a);
d6624158 240 n('empty?') = @(a) length(a) == 0;
47699629
JM
241 % workaround Octave always giving length(a) of 1
242 n('count') = @(a) 0 + length(a);
243 n('apply') = @(varargin) core.apply(varargin{:});
244 n('map') = @(varargin) core.map(varargin{:});
425233e3 245 n('conj') = @(varargin) core.conj(varargin{:});
53942f88 246
47699629
JM
247 n('with-meta') = @(a,b) core.with_meta(a,b);
248 n('meta') = @(a) core.meta(a);
249 n('atom') = @(a) types.Atom(a);
53942f88
JM
250 n('atom?') = @(a) isa(a, 'types.Atom');
251 n('deref') = @(a) a.val;
47699629
JM
252 n('reset!') = @(a,b) core.reset_BANG(a,b);
253 n('swap!') = @(varargin) core.swap_BANG(varargin{:});
d6624158
JM
254 end
255 end
256end
257