1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-20 18:18:51 +03:00
mal/matlab/core.m
2016-02-11 09:19:53 -06:00

291 lines
9.7 KiB
Matlab

classdef core
methods(Static)
function ret = throw(obj)
ret = type_utils.nil;
if exist('OCTAVE_VERSION', 'builtin') ~= 0
% Until Octave has MException objects, we need to
% store the error object globally to be able to pass
% it to the error handler.
global error_object;
error_object = obj;
exc = struct('identifier', 'MalException:object',...
'message', 'MalException');
rethrow(exc);
else
throw(types.MalException(obj));
end
end
function str = pr_str(varargin)
strs = cellfun(@(s) printer.pr_str(s,true), varargin, ...
'UniformOutput', false);
str = strjoin(strs, ' ');
end
function str = do_str(varargin)
strs = cellfun(@(s) printer.pr_str(s,false), varargin, ...
'UniformOutput', false);
str = strjoin(strs, '');
end
function ret = prn(varargin)
strs = cellfun(@(s) printer.pr_str(s,true), varargin, ...
'UniformOutput', false);
fprintf('%s\n', strjoin(strs, ' '));
ret = type_utils.nil;
end
function ret = println(varargin)
strs = cellfun(@(s) printer.pr_str(s,false), varargin, ...
'UniformOutput', false);
fprintf('%s\n', strjoin(strs, ' '));
ret = type_utils.nil;
end
function ret = time_ms()
secs = now-repmat(datenum('1970-1-1 00:00:00'),size(now));
ret = floor(secs.*repmat(24*3600.0*1000,size(now)));
end
function new_hm = assoc(hm, varargin)
new_hm = clone(hm);
for i=1:2:length(varargin)
new_hm.set(varargin{i}, varargin{i+1});
end
end
function new_hm = dissoc(hm, varargin)
new_hm = clone(hm);
ks = intersect(hm.keys(),varargin);
if exist('OCTAVE_VERSION', 'builtin') ~= 0
new_hm.data.remove(ks);
else
remove(new_hm.data, ks);
end
end
function ret = get(hm, key)
if isa(hm, 'types.Nil')
ret = type_utils.nil;
elseif hm.data.isKey(key)
ret = hm.data(key);
else
ret = type_utils.nil;
end
end
function ret = keys(hm)
ks = hm.keys();
ret = types.List(ks{:});
end
function ret = vals(hm)
vs = hm.values();
ret = types.List(vs{:});
end
function ret = cons(a, seq)
cella = [{a}, seq.data];
ret = types.List(cella{:});
end
function ret = concat(varargin)
if nargin == 0
cella = {};
else
cells = cellfun(@(x) x.data, varargin, ...
'UniformOutput', false);
cella = cat(2,cells{:});
end
ret = types.List(cella{:});
end
function ret = first(seq)
if isa(seq, 'types.Nil')
ret = type_utils.nil;
elseif length(seq) < 1
ret = type_utils.nil;
else
ret = seq.get(1);
end
end
function ret = rest(seq)
if isa(seq, 'types.Nil')
ret = types.List();
else
cella = seq.data(2:end);
ret = types.List(cella{:});
end
end
function ret = nth(seq, idx)
if idx+1 > length(seq)
throw(MException('Range:nth', ...
'nth: index out of range'))
end
ret = seq.get(idx+1);
end
function ret = apply(varargin)
f = varargin{1};
if isa(f, 'types.Function')
f = f.fn;
end
first_args = varargin(2:end-1);
rest_args = varargin{end}.data;
args = [first_args rest_args];
ret = f(args{:});
end
function ret = map(f, lst)
if isa(f, 'types.Function')
f = f.fn;
end
cells = cellfun(@(x) f(x), lst.data, 'UniformOutput', false);
ret = types.List(cells{:});
end
function ret = conj(varargin)
seq = varargin{1};
args = varargin(2:end);
if type_utils.list_Q(seq)
cella = [fliplr(args), seq.data];
ret = types.List(cella{:});
else
cella = [seq.data, args];
ret = types.Vector(cella{:});
end
end
function ret = seq(obj)
if type_utils.list_Q(obj)
if length(obj) > 0
ret = obj;
else
ret = type_utils.nil;
end
elseif type_utils.vector_Q(obj)
if length(obj) > 0
ret = types.List(obj.data{:});
else
ret = type_utils.nil;
end
elseif type_utils.string_Q(obj)
if length(obj) > 0
cells = cellfun(@(c) char(c),...
num2cell(double(obj)),...
'UniformOutput', false);
ret = types.List(cells{:});
else
ret = type_utils.nil;
end
elseif isa(obj, 'types.Nil')
ret = type_utils.nil;
else
throw(MException('Type:seq',...
'seq: called on non-sequence'))
end
end
function new_obj = with_meta(obj, meta)
new_obj = clone(obj);
new_obj.meta = meta;
end
function meta = meta(obj)
switch class(obj)
case {'types.List', 'types.Vector',
'types.HashMap', 'types.Function'}
meta = obj.meta;
otherwise
meta = type_utils.nil;
end
end
function ret = reset_BANG(atm, val)
atm.val = val;
ret = val;
end
function ret = swap_BANG(atm, f, varargin)
args = [{atm.val} varargin];
if isa(f, 'types.Function')
f = f.fn;
end
atm.val = f(args{:});
ret = atm.val;
end
function n = ns()
if exist('OCTAVE_VERSION', 'builtin') ~= 0
n = Dict();
else
n = containers.Map();
end
n('=') = @(a,b) type_utils.equal(a,b);
n('throw') = @(a) core.throw(a);
n('nil?') = @(a) isa(a, 'types.Nil');
n('true?') = @(a) isa(a, 'logical') && a == true;
n('false?') = @(a) isa(a, 'logical') && a == false;
n('string?') = @(a) type_utils.string_Q(a);
n('symbol') = @(a) types.Symbol(a);
n('symbol?') = @(a) isa(a, 'types.Symbol');
n('keyword') = @(a) type_utils.keyword(a);
n('keyword?') = @(a) type_utils.keyword_Q(a);
n('pr-str') = @(varargin) core.pr_str(varargin{:});
n('str') = @(varargin) core.do_str(varargin{:});
n('prn') = @(varargin) core.prn(varargin{:});
n('println') = @(varargin) core.println(varargin{:});
n('read-string') = @(a) reader.read_str(a);
n('readline') = @(p) input(p, 's');
n('slurp') = @(a) fileread(a);
n('<') = @(a,b) a<b;
n('<=') = @(a,b) a<=b;
n('>') = @(a,b) a>b;
n('>=') = @(a,b) a>=b;
n('+') = @(a,b) a+b;
n('-') = @(a,b) a-b;
n('*') = @(a,b) a*b;
n('/') = @(a,b) floor(a/b);
n('time-ms') = @() core.time_ms();
n('list') = @(varargin) types.List(varargin{:});
n('list?') = @(a) type_utils.list_Q(a);
n('vector') = @(varargin) types.Vector(varargin{:});
n('vector?') = @(a) type_utils.vector_Q(a);
n('hash-map') = @(varargin) types.HashMap(varargin{:});
n('map?') = @(a) type_utils.hash_map_Q(a);
n('assoc') = @(varargin) core.assoc(varargin{:});
n('dissoc') = @(varargin) core.dissoc(varargin{:});
n('get') = @(a,b) core.get(a,b);
n('contains?') = @(a,b) a.data.isKey(b);
n('keys') = @(a) core.keys(a);
n('vals') = @(a) core.vals(a);
n('sequential?') = @(a) type_utils.sequential_Q(a);
n('cons') = @(a,b) core.cons(a,b);
n('concat') = @(varargin) core.concat(varargin{:});
n('nth') = @(a,b) core.nth(a,b);
n('first') = @(a) core.first(a);
n('rest') = @(a) core.rest(a);
n('empty?') = @(a) length(a) == 0;
% workaround Octave always giving length(a) of 1
n('count') = @(a) 0 + length(a);
n('apply') = @(varargin) core.apply(varargin{:});
n('map') = @(varargin) core.map(varargin{:});
n('conj') = @(varargin) core.conj(varargin{:});
n('seq') = @(a) core.seq(a);
n('with-meta') = @(a,b) core.with_meta(a,b);
n('meta') = @(a) core.meta(a);
n('atom') = @(a) types.Atom(a);
n('atom?') = @(a) isa(a, 'types.Atom');
n('deref') = @(a) a.val;
n('reset!') = @(a,b) core.reset_BANG(a,b);
n('swap!') = @(varargin) core.swap_BANG(varargin{:});
end
end
end