Switch List to full object like vector and hash-map.
--- /dev/null
+classdef HashMap < handle
+ properties
+ data = containers.Map();
+ meta = types.nil;
+ end
+ methods
+ function obj = HashMap(varargin)
+ if nargin == 0
+ obj.data = containers.Map();
+ else
+ obj.data = containers.Map(varargin(1:2:end), ...
+ varargin(2:2:end));
+ end
+ end
+
+ function len = length(obj)
+ len = length(obj.data);
+ end
+
+ function ret = get(obj, key)
+ ret = obj.data(key);
+ end
+
+ function ret = set(obj, key, val)
+ obj.data(key) = val;
+ ret = val;
+ end
+
+ function ret = keys(obj)
+ ret = obj.data.keys();
+ end
+
+ function ret = values(obj)
+ ret = obj.data.values();
+ end
+
+ function ret = clone(obj)
+ ret = types.HashMap();
+ if length(obj) > 0
+ ret.data = containers.Map(obj.data.keys(), obj.data.values());
+ else
+ ret.data = containers.Map();
+ end
+ ret.meta = obj.meta;
+ end
+ end
+end
--- /dev/null
+classdef List < handle
+ properties
+ data = {}
+ meta = types.nil;
+ end
+ methods
+ function obj = List(varargin)
+ obj.data = varargin;
+ end
+
+ function len = length(obj)
+ len = length(obj.data);
+ end
+
+ function ret = get(obj, idx)
+ ret = obj.data{idx};
+ end
+
+ function ret = set(obj, key, val)
+ obj.data{key} = val;
+ ret = val;
+ end
+
+ function ret = append(obj, val)
+ obj.data{end+1} = val;
+ ret = val;
+ end
+
+ function ret = slice(obj, start, last)
+ if nargin < 3
+ last = length(obj.data);
+ end
+ ret = types.List(obj.data{start:end});
+ end
+
+% function varargout = subsref(vec, S)
+% % This doesn't work for ranges
+% [varargout{1:nargout}] = builtin('subsref', vec.data, S);
+%
+% varargout = cell(1,max(1,nargout));
+% [varargout{:}] = builtin('subsref',vec.data,S);
+%
+%% switch S.type
+%% case '()'
+%% varargout = cell(1,numel(vec));
+%% varargout{1} = builtin('subsref', vec.data, S);
+%% case '{}'
+%% varargout = cell(1,numel(vec));
+%% varargout{1} = builtin('subsref', vec.data, S);
+%% case '.'
+%% error('Vector property access not yet implemented');
+%% end
+% end
+
+% %function n = numel(varargin)
+% % n = 1;
+% %end
+
+ end
+end
--- /dev/null
+classdef Vector < types.List
+ methods
+ function obj = Vector(varargin)
+ obj.data = varargin;
+ end
+
+ function ret = slice(obj, start, last)
+ if nargin < 3
+ last = length(obj.data);
+ end
+ ret = types.Vector(obj.data{2:end});
+ end
+
+ end
+end
if nargin > 1
env = Env(outer);
for i=1:length(binds)
- k = binds{i}.name;
+ k = binds.get(i).name;
if strcmp(k, '&')
- env.data(binds{i+1}.name) = exprs(i:end);
+ env.data(binds.get(i+1).name) = exprs.slice(i);
break;
else
- env.data(k) = exprs{i};
+ env.data(k) = exprs.get(i);
end
end
end
SOURCES_BASE = Reader.m types/Symbol.m reader.m printer.m
#SOURCES_LISP = env.m core.m stepA_interop.m
-SOURCES_LISP = step1_read_print.m
+SOURCES_LISP = stepA_interop.m
SOURCES = $(SOURCES_BASE) $(SOURCES_LISP)
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);
+ remove(new_hm.data, ks);
+ end
+
+ function ret = get(hm, key)
+ if hm == types.nil
+ ret = types.nil;
+ else
+ if hm.data.isKey(key)
+ ret = hm.data(key);
+ else
+ ret = types.nil;
+ end
+ 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
- ret = {};
+ cella = {};
else
- ret = cat(2,varargin{:});
+ cells = cellfun(@(x) x.data, varargin, ...
+ 'UniformOutput', false);
+ cella = cat(2,cells{:});
end
+ ret = types.List(cella{:});
end
function ret = first(seq)
if length(seq) < 1
ret = types.nil;
else
- ret = seq{1};
+ ret = seq.get(1);
end
end
+ function ret = rest(seq)
+ cella = seq.data(2:end);
+ ret = types.List(cella{:});
+ end
+
function ret = nth(seq, idx)
if idx+1 > length(seq)
throw(MException('Range:nth', ...
'nth: index out of range'))
end
- ret = seq{idx+1};
+ ret = seq.get(idx+1);
end
function ret = apply(varargin)
f = f.fn;
end
first_args = varargin(2:end-1);
- rest_args = varargin{end};
+ rest_args = varargin{end}.data;
args = [first_args rest_args];
ret = f(args{:});
end
if isa(f, 'types.Function')
f = f.fn;
end
- ret = cellfun(@(x) f(x), lst, 'UniformOutput', false);
+ cells = cellfun(@(x) f(x), lst.data, 'UniformOutput', false);
+ ret = types.List(cells{:});
end
function n = ns()
n('false?') = @(a) isa(a, 'logical') && a == false;
n('symbol') = @(a) types.Symbol(a);
n('symbol?') = @(a) isa(a, 'types.Symbol');
+ n('keyword') = @types.keyword;
+ n('keyword?') = @types.keyword_Q;
n('pr-str') = @core.pr_str;
n('str') = @core.do_str;
n('/') = @(a,b) floor(a/b);
n('time-ms') = @core.time_ms;
- n('list') = @(varargin) varargin;
- n('list?') = @iscell;
+ n('list') = @(varargin) types.List(varargin{:});
+ n('list?') = @types.list_Q;
+ n('vector') = @(varargin) types.Vector(varargin{:});
+ n('vector?') = @types.vector_Q;
+ n('hash-map') = @(varargin) types.HashMap(varargin{:});
+ n('map?') = @types.hash_map_Q;
+ n('assoc') = @core.assoc;
+ n('dissoc') = @core.dissoc;
+ n('get') = @core.get;
+ n('contains?') = @(a,b) a.data.isKey(b);
+ n('keys') = @core.keys;
+ n('vals') = @core.vals;
- n('cons') = @(a,b) [{a}, b];
+ n('sequential?') = @types.sequential_Q;
+ n('cons') = @core.cons;
n('concat') = @core.concat;
n('nth') = @core.nth;
n('first') = @core.first;
- n('rest') = @(a) a(2:end);
+ n('rest') = @core.rest;
n('empty?') = @(a) length(a) == 0;
n('count') = @(a) length(a);
n('apply') = @core.apply;
case 'double'
str = num2str(obj);
case 'char'
- if print_readably
- str = strrep(obj, '\', '\\');
- str = strrep(str, '"', '\"');
- str = strrep(str, char(10), '\n');
- str = strcat('"', str, '"');
+ if types.keyword_Q(obj)
+ str = strcat(':', obj(2:end));
else
- str = obj;
+ if print_readably
+ str = strrep(obj, '\', '\\');
+ str = strrep(str, '"', '\"');
+ str = strrep(str, char(10), '\n');
+ str = strcat('"', str, '"');
+ else
+ str = obj;
+ end
end
- case 'cell'
+ case 'types.List'
strs = cellfun(@(x) printer.pr_str(x, print_readably), ...
- obj, 'UniformOutput', false);
+ obj.data, 'UniformOutput', false);
str = strcat('(', strjoin(strs, ' '), ')');
+ case 'types.Vector'
+ strs = cellfun(@(x) printer.pr_str(x, print_readably), ...
+ obj.data, 'UniformOutput', false);
+ str = strcat('[', strjoin(strs, ' '), ']');
+ case 'types.HashMap'
+ strs = {};
+ ks = obj.keys();
+ for i=1:length(ks)
+ k = ks{i};
+ strs{end+1} = printer.pr_str(k, print_readably);
+ strs{end+1} = printer.pr_str(obj.get(k), print_readably);
+ end
+ str = strcat('{', strjoin(strs, ' '), '}');
case 'types.Nil'
str = 'nil';
case 'logical'
atm = token(2:length(token)-1);
atm = strrep(atm, '\"', '"');
atm = strrep(atm, '\n', char(10));
+ elseif strcmp(token(1), ':')
+ atm = types.keyword(token);
elseif strcmp(token, 'nil')
atm = types.nil;
elseif strcmp(token, 'true')
end
end
- function lst = read_list(rdr)
- %fprintf('in read_list\n');
- lst = {};
+ function seq = read_seq(rdr, start, last)
+ %fprintf('in read_seq\n');
+ seq = {};
token = rdr.next();
- if not(strcmp(token, '('))
- error('expected ''(''');
+ if not(strcmp(token, start))
+ error(strcat('expected ''', start, ''''));
end
token = rdr.peek();
while true
if eq(token, false)
- error('expected '')''');
+ error(strcat('expected ''', last, ''''));
end
- if strcmp(token, ')'), break, end
- lst{length(lst)+1} = reader.read_form(rdr);
+ if strcmp(token, last), break, end
+ seq{end+1} = reader.read_form(rdr);
token = rdr.peek();
end
rdr.next();
end
+ function lst = read_list(rdr)
+ seq = reader.read_seq(rdr, '(', ')');
+ lst = types.List(seq{:});
+ end
+
+ function vec = read_vector(rdr)
+ seq = reader.read_seq(rdr, '[', ']');
+ vec = types.Vector(seq{:});
+ end
+
+ function map = read_hash_map(rdr)
+ seq = reader.read_seq(rdr, '{', '}');
+ map = types.HashMap(seq{:});
+ end
+
function ast = read_form(rdr)
%fprintf('in read_form\n');
token = rdr.peek();
switch token
case ''''
rdr.next();
- ast = {types.Symbol('quote'), reader.read_form(rdr)};
+ ast = types.List(types.Symbol('quote'), ...
+ reader.read_form(rdr));
case '`'
rdr.next();
- ast = {types.Symbol('quasiquote'), reader.read_form(rdr)};
+ ast = types.List(types.Symbol('quasiquote'), ...
+ reader.read_form(rdr));
case '~'
rdr.next();
- ast = {types.Symbol('unquote'), reader.read_form(rdr)};
+ ast = types.List(types.Symbol('unquote'), ...
+ reader.read_form(rdr));
case '~@'
rdr.next();
- ast = {types.Symbol('splice-unquote'), reader.read_form(rdr)};
+ ast = types.List(types.Symbol('splice-unquote'), ...
+ reader.read_form(rdr));
case ')'
error('unexpected '')''');
case '('
ast = reader.read_list(rdr);
+ case ']'
+ error('unexpected '']''');
+ case '['
+ ast = reader.read_vector(rdr);
+ case '}'
+ error('unexpected ''}''');
+ case '{'
+ ast = reader.read_hash_map(rdr);
otherwise
ast = reader.read_atom(rdr);
end
switch class(ast)
case 'types.Symbol'
ret = env(ast.name);
- case 'cell'
- ret = {};
+ case 'types.List'
+ ret = types.List();
for i=1:length(ast)
- ret{end+1} = EVAL(ast{i}, env);
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.Vector'
+ ret = types.Vector();
+ for i=1:length(ast)
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.HashMap'
+ ret = types.HashMap();
+ ks = ast.keys();
+ for i=1:length(ks)
+ k = ks{i};
+ ret.set(EVAL(k, env), EVAL(ast.get(k), env));
end
otherwise
ret = ast;
end
function ret = EVAL(ast, env)
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = eval_ast(ast, env);
return;
end
% apply
el = eval_ast(ast, env);
- f = el{1};
- args = el(2:end);
+ f = el.get(1);
+ args = el.data(2:end);
ret = f(args{:});
end
switch class(ast)
case 'types.Symbol'
ret = env.get(ast);
- case 'cell'
- ret = {};
+ case 'types.List'
+ ret = types.List();
for i=1:length(ast)
- ret{end+1} = EVAL(ast{i}, env);
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.Vector'
+ ret = types.Vector();
+ for i=1:length(ast)
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.HashMap'
+ ret = types.HashMap();
+ ks = ast.keys();
+ for i=1:length(ks)
+ k = ks{i};
+ ret.set(EVAL(k, env), EVAL(ast.get(k), env));
end
otherwise
ret = ast;
end
function ret = EVAL(ast, env)
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = eval_ast(ast, env);
return;
end
% apply
- if isa(ast{1},'types.Symbol')
- a1sym = ast{1}.name;
+ if isa(ast.get(1),'types.Symbol')
+ a1sym = ast.get(1).name;
else
a1sym = '_@$fn$@_';
end
switch (a1sym)
case 'def!'
- ret = env.set(ast{2}, EVAL(ast{3}, env));
+ ret = env.set(ast.get(2), EVAL(ast.get(3), env));
case 'let*'
let_env = Env(env);
- for i=1:2:length(ast{2})
- let_env.set(ast{2}{i}, EVAL(ast{2}{i+1}, let_env));
+ for i=1:2:length(ast.get(2))
+ let_env.set(ast.get(2).get(i), EVAL(ast.get(2).get(i+1), let_env));
end
- ret = EVAL(ast{3}, let_env);
+ ret = EVAL(ast.get(3), let_env);
otherwise
el = eval_ast(ast, env);
- f = el{1};
- args = el(2:end);
+ f = el.get(1);
+ args = el.data(2:end);
ret = f(args{:});
end
end
switch class(ast)
case 'types.Symbol'
ret = env.get(ast);
- case 'cell'
- ret = {};
+ case 'types.List'
+ ret = types.List();
for i=1:length(ast)
- ret{end+1} = EVAL(ast{i}, env);
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.Vector'
+ ret = types.Vector();
+ for i=1:length(ast)
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.HashMap'
+ ret = types.HashMap();
+ ks = ast.keys();
+ for i=1:length(ks)
+ k = ks{i};
+ ret.set(EVAL(k, env), EVAL(ast.get(k), env));
end
otherwise
ret = ast;
end
function ret = EVAL(ast, env)
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = eval_ast(ast, env);
return;
end
% apply
- if isa(ast{1},'types.Symbol')
- a1sym = ast{1}.name;
+ if isa(ast.get(1),'types.Symbol')
+ a1sym = ast.get(1).name;
else
a1sym = '_@$fn$@_';
end
switch (a1sym)
case 'def!'
- ret = env.set(ast{2}, EVAL(ast{3}, env));
+ ret = env.set(ast.get(2), EVAL(ast.get(3), env));
case 'let*'
let_env = Env(env);
- for i=1:2:length(ast{2})
- let_env.set(ast{2}{i}, EVAL(ast{2}{i+1}, let_env));
+ for i=1:2:length(ast.get(2))
+ let_env.set(ast.get(2).get(i), EVAL(ast.get(2).get(i+1), let_env));
end
- ret = EVAL(ast{3}, let_env);
+ ret = EVAL(ast.get(3), let_env);
case 'do'
- el = eval_ast(ast(2:end), env);
- ret = el{end};
+ el = eval_ast(ast.slice(2), env);
+ ret = el.get(length(el));
case 'if'
- cond = EVAL(ast{2}, env);
+ cond = EVAL(ast.get(2), env);
if strcmp(class(cond), 'types.Nil') || ...
(islogical(cond) && cond == false)
if length(ast) > 3
- ret = EVAL(ast{4}, env);
+ ret = EVAL(ast.get(4), env);
else
- ret = types.nil;
+ ret = types.nil;
end
else
- ret = EVAL(ast{3}, env);
+ ret = EVAL(ast.get(3), env);
end
case 'fn*'
- ret = @(varargin) EVAL(ast{3}, Env(env, ast{2}, varargin));
+ ret = @(varargin) EVAL(ast.get(3), Env(env, ast.get(2), ...
+ types.List(varargin{:})));
otherwise
el = eval_ast(ast, env);
- f = el{1};
- args = el(2:end);
+ f = el.get(1);
+ args = el.data(2:end);
ret = f(args{:});
end
end
switch class(ast)
case 'types.Symbol'
ret = env.get(ast);
- case 'cell'
- ret = {};
+ case 'types.List'
+ ret = types.List();
for i=1:length(ast)
- ret{end+1} = EVAL(ast{i}, env);
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.Vector'
+ ret = types.Vector();
+ for i=1:length(ast)
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.HashMap'
+ ret = types.HashMap();
+ ks = ast.keys();
+ for i=1:length(ks)
+ k = ks{i};
+ ret.set(EVAL(k, env), EVAL(ast.get(k), env));
end
otherwise
ret = ast;
function ret = EVAL(ast, env)
while true
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = eval_ast(ast, env);
return;
end
% apply
- if isa(ast{1},'types.Symbol')
- a1sym = ast{1}.name;
+ if isa(ast.get(1),'types.Symbol')
+ a1sym = ast.get(1).name;
else
a1sym = '_@$fn$@_';
end
switch (a1sym)
case 'def!'
- ret = env.set(ast{2}, EVAL(ast{3}, env));
+ ret = env.set(ast.get(2), EVAL(ast.get(3), env));
return;
case 'let*'
let_env = Env(env);
- for i=1:2:length(ast{2})
- let_env.set(ast{2}{i}, EVAL(ast{2}{i+1}, let_env));
+ for i=1:2:length(ast.get(2))
+ let_env.set(ast.get(2).get(i), EVAL(ast.get(2).get(i+1), let_env));
end
env = let_env;
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
case 'do'
- el = eval_ast(ast(2:end-1), env);
- ast = ast{end}; % TCO
+ el = eval_ast(ast.slice(2,length(ast)-1), env);
+ ast = ast.get(length(ast)); % TCO
case 'if'
- cond = EVAL(ast{2}, env);
+ cond = EVAL(ast.get(2), env);
if strcmp(class(cond), 'types.Nil') || ...
(islogical(cond) && cond == false)
if length(ast) > 3
- ast = ast{4}; % TCO
+ ast = ast.get(4); % TCO
else
ret = types.nil;
return;
end
else
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
end
case 'fn*'
- fn = @(varargin) EVAL(ast{3}, Env(env, ast{2}, varargin));
- ret = types.Function(fn, ast{3}, env, ast{2});
+ fn = @(varargin) EVAL(ast.get(3), Env(env, ast.get(2), ...
+ types.List(varargin{:})));
+ ret = types.Function(fn, ast.get(3), env, ast.get(2));
return;
otherwise
el = eval_ast(ast, env);
- f = el{1};
- args = el(2:end);
+ f = el.get(1);
+ args = el.slice(2);
if isa(f, 'types.Function')
env = Env(f.env, f.params, args);
ast = f.ast; % TCO
else
- ret = f(args{:});
+ ret = f(args.data{:});
return
end
end
switch class(ast)
case 'types.Symbol'
ret = env.get(ast);
- case 'cell'
- ret = {};
+ case 'types.List'
+ ret = types.List();
for i=1:length(ast)
- ret{end+1} = EVAL(ast{i}, env);
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.Vector'
+ ret = types.Vector();
+ for i=1:length(ast)
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.HashMap'
+ ret = types.HashMap();
+ ks = ast.keys();
+ for i=1:length(ks)
+ k = ks{i};
+ ret.set(EVAL(k, env), EVAL(ast.get(k), env));
end
otherwise
ret = ast;
function ret = EVAL(ast, env)
while true
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = eval_ast(ast, env);
return;
end
% apply
- if isa(ast{1},'types.Symbol')
- a1sym = ast{1}.name;
+ if isa(ast.get(1),'types.Symbol')
+ a1sym = ast.get(1).name;
else
a1sym = '_@$fn$@_';
end
switch (a1sym)
case 'def!'
- ret = env.set(ast{2}, EVAL(ast{3}, env));
+ ret = env.set(ast.get(2), EVAL(ast.get(3), env));
return;
case 'let*'
let_env = Env(env);
- for i=1:2:length(ast{2})
- let_env.set(ast{2}{i}, EVAL(ast{2}{i+1}, let_env));
+ for i=1:2:length(ast.get(2))
+ let_env.set(ast.get(2).get(i), EVAL(ast.get(2).get(i+1), let_env));
end
env = let_env;
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
case 'do'
- el = eval_ast(ast(2:end-1), env);
- ast = ast{end}; % TCO
+ el = eval_ast(ast.slice(2,length(ast)-1), env);
+ ast = ast.get(length(ast)); % TCO
case 'if'
- cond = EVAL(ast{2}, env);
+ cond = EVAL(ast.get(2), env);
if strcmp(class(cond), 'types.Nil') || ...
(islogical(cond) && cond == false)
if length(ast) > 3
- ast = ast{4}; % TCO
+ ast = ast.get(4); % TCO
else
ret = types.nil;
return;
end
else
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
end
case 'fn*'
- fn = @(varargin) EVAL(ast{3}, Env(env, ast{2}, varargin));
- ret = types.Function(fn, ast{3}, env, ast{2});
+ fn = @(varargin) EVAL(ast.get(3), Env(env, ast.get(2), ...
+ types.List(varargin{:})));
+ ret = types.Function(fn, ast.get(3), env, ast.get(2));
return;
otherwise
el = eval_ast(ast, env);
- f = el{1};
- args = el(2:end);
+ f = el.get(1);
+ args = el.slice(2);
if isa(f, 'types.Function')
env = Env(f.env, f.params, args);
ast = f.ast; % TCO
else
- ret = f(args{:});
+ ret = f(args.data{:});
return
end
end
repl_env.set(types.Symbol(k), ns(k));
end
repl_env.set(types.Symbol('eval'), @(a) EVAL(a, repl_env));
- repl_env.set(types.Symbol('*ARGV*'), args(2:end));
+ rest_args = args(2:end);
+ repl_env.set(types.Symbol('*ARGV*'), types.List(rest_args{:}));
% core.mal: defined using the langauge itself
rep('(def! not (fn* (a) (if a false true)))', repl_env);
% eval
function ret = is_pair(ast)
- ret = iscell(ast) && length(ast) > 0;
+ ret = types.sequential_Q(ast) && length(ast) > 0;
end
function ret = quasiquote(ast)
if ~is_pair(ast)
- ret = {types.Symbol('quote'), ast};
- elseif isa(ast{1},'types.Symbol') && ...
- strcmp(ast{1}.name, 'unquote')
- ret = ast{2};
- elseif is_pair(ast{1}) && isa(ast{1}{1},'types.Symbol') && ...
- strcmp(ast{1}{1}.name, 'splice-unquote')
- ret = {types.Symbol('concat'), ...
- ast{1}{2}, ...
- quasiquote(ast(2:end))};
+ ret = types.List(types.Symbol('quote'), ast);
+ elseif isa(ast.get(1),'types.Symbol') && ...
+ strcmp(ast.get(1).name, 'unquote')
+ ret = ast.get(2);
+ elseif is_pair(ast.get(1)) && ...
+ isa(ast.get(1).get(1),'types.Symbol') && ...
+ strcmp(ast.get(1).get(1).name, 'splice-unquote')
+ ret = types.List(types.Symbol('concat'), ...
+ ast.get(1).get(2), ...
+ quasiquote(ast.slice(2)));
else
- ret = {types.Symbol('cons'), ...
- quasiquote(ast{1}), ...
- quasiquote(ast(2:end))};
+ ret = types.List(types.Symbol('cons'), ...
+ quasiquote(ast.get(1)), ...
+ quasiquote(ast.slice(2)));
end
end
switch class(ast)
case 'types.Symbol'
ret = env.get(ast);
- case 'cell'
- ret = {};
+ case 'types.List'
+ ret = types.List();
for i=1:length(ast)
- ret{end+1} = EVAL(ast{i}, env);
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.Vector'
+ ret = types.Vector();
+ for i=1:length(ast)
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.HashMap'
+ ret = types.HashMap();
+ ks = ast.keys();
+ for i=1:length(ks)
+ k = ks{i};
+ ret.set(EVAL(k, env), EVAL(ast.get(k), env));
end
otherwise
ret = ast;
function ret = EVAL(ast, env)
while true
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = eval_ast(ast, env);
return;
end
% apply
- if isa(ast{1},'types.Symbol')
- a1sym = ast{1}.name;
+ if isa(ast.get(1),'types.Symbol')
+ a1sym = ast.get(1).name;
else
a1sym = '_@$fn$@_';
end
switch (a1sym)
case 'def!'
- ret = env.set(ast{2}, EVAL(ast{3}, env));
+ ret = env.set(ast.get(2), EVAL(ast.get(3), env));
return;
case 'let*'
let_env = Env(env);
- for i=1:2:length(ast{2})
- let_env.set(ast{2}{i}, EVAL(ast{2}{i+1}, let_env));
+ for i=1:2:length(ast.get(2))
+ let_env.set(ast.get(2).get(i), EVAL(ast.get(2).get(i+1), let_env));
end
env = let_env;
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
case 'quote'
- ret = ast{2};
+ ret = ast.get(2);
return;
case 'quasiquote'
- ast = quasiquote(ast{2}); % TCO
+ ast = quasiquote(ast.get(2)); % TCO
case 'do'
- el = eval_ast(ast(2:end-1), env);
- ast = ast{end}; % TCO
+ el = eval_ast(ast.slice(2,length(ast)-1), env);
+ ast = ast.get(length(ast)); % TCO
case 'if'
- cond = EVAL(ast{2}, env);
+ cond = EVAL(ast.get(2), env);
if strcmp(class(cond), 'types.Nil') || ...
(islogical(cond) && cond == false)
if length(ast) > 3
- ast = ast{4}; % TCO
+ ast = ast.get(4); % TCO
else
ret = types.nil;
return;
end
else
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
end
case 'fn*'
- fn = @(varargin) EVAL(ast{3}, Env(env, ast{2}, varargin));
- ret = types.Function(fn, ast{3}, env, ast{2});
+ fn = @(varargin) EVAL(ast.get(3), Env(env, ast.get(2), ...
+ types.List(varargin{:})));
+ ret = types.Function(fn, ast.get(3), env, ast.get(2));
return;
otherwise
el = eval_ast(ast, env);
- f = el{1};
- args = el(2:end);
+ f = el.get(1);
+ args = el.slice(2);
if isa(f, 'types.Function')
env = Env(f.env, f.params, args);
ast = f.ast; % TCO
else
- ret = f(args{:});
+ ret = f(args.data{:});
return
end
end
repl_env.set(types.Symbol(k), ns(k));
end
repl_env.set(types.Symbol('eval'), @(a) EVAL(a, repl_env));
- repl_env.set(types.Symbol('*ARGV*'), args(2:end));
+ rest_args = args(2:end);
+ repl_env.set(types.Symbol('*ARGV*'), types.List(rest_args{:}));
% core.mal: defined using the langauge itself
rep('(def! not (fn* (a) (if a false true)))', repl_env);
% eval
function ret = is_pair(ast)
- ret = iscell(ast) && length(ast) > 0;
+ ret = types.sequential_Q(ast) && length(ast) > 0;
end
function ret = quasiquote(ast)
if ~is_pair(ast)
- ret = {types.Symbol('quote'), ast};
- elseif isa(ast{1},'types.Symbol') && ...
- strcmp(ast{1}.name, 'unquote')
- ret = ast{2};
- elseif is_pair(ast{1}) && isa(ast{1}{1},'types.Symbol') && ...
- strcmp(ast{1}{1}.name, 'splice-unquote')
- ret = {types.Symbol('concat'), ...
- ast{1}{2}, ...
- quasiquote(ast(2:end))};
+ ret = types.List(types.Symbol('quote'), ast);
+ elseif isa(ast.get(1),'types.Symbol') && ...
+ strcmp(ast.get(1).name, 'unquote')
+ ret = ast.get(2);
+ elseif is_pair(ast.get(1)) && ...
+ isa(ast.get(1).get(1),'types.Symbol') && ...
+ strcmp(ast.get(1).get(1).name, 'splice-unquote')
+ ret = types.List(types.Symbol('concat'), ...
+ ast.get(1).get(2), ...
+ quasiquote(ast.slice(2)));
else
- ret = {types.Symbol('cons'), ...
- quasiquote(ast{1}), ...
- quasiquote(ast(2:end))};
+ ret = types.List(types.Symbol('cons'), ...
+ quasiquote(ast.get(1)), ...
+ quasiquote(ast.slice(2)));
end
end
function ret = is_macro_call(ast, env)
- if iscell(ast) && isa(ast{1}, 'types.Symbol') && ...
- ~islogical(env.find(ast{1}))
- f = env.get(ast{1});
+ if types.list_Q(ast) && isa(ast.get(1), 'types.Symbol') && ...
+ ~islogical(env.find(ast.get(1)))
+ f = env.get(ast.get(1));
ret = isa(f,'types.Function') && f.is_macro;
else
ret = false;
function ret = macroexpand(ast, env)
while is_macro_call(ast, env)
- mac = env.get(ast{1});
- ast = mac.fn(ast{2:end});
+ mac = env.get(ast.get(1));
+ args = ast.slice(2);
+ ast = mac.fn(args.data{:});
end
ret = ast;
end
switch class(ast)
case 'types.Symbol'
ret = env.get(ast);
- case 'cell'
- ret = {};
+ case 'types.List'
+ ret = types.List();
for i=1:length(ast)
- ret{end+1} = EVAL(ast{i}, env);
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.Vector'
+ ret = types.Vector();
+ for i=1:length(ast)
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.HashMap'
+ ret = types.HashMap();
+ ks = ast.keys();
+ for i=1:length(ks)
+ k = ks{i};
+ ret.set(EVAL(k, env), EVAL(ast.get(k), env));
end
otherwise
ret = ast;
function ret = EVAL(ast, env)
while true
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = eval_ast(ast, env);
return;
end
% apply
ast = macroexpand(ast, env);
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = ast;
return;
end
- if isa(ast{1},'types.Symbol')
- a1sym = ast{1}.name;
+ if isa(ast.get(1),'types.Symbol')
+ a1sym = ast.get(1).name;
else
a1sym = '_@$fn$@_';
end
switch (a1sym)
case 'def!'
- ret = env.set(ast{2}, EVAL(ast{3}, env));
+ ret = env.set(ast.get(2), EVAL(ast.get(3), env));
return;
case 'let*'
let_env = Env(env);
- for i=1:2:length(ast{2})
- let_env.set(ast{2}{i}, EVAL(ast{2}{i+1}, let_env));
+ for i=1:2:length(ast.get(2))
+ let_env.set(ast.get(2).get(i), EVAL(ast.get(2).get(i+1), let_env));
end
env = let_env;
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
case 'quote'
- ret = ast{2};
+ ret = ast.get(2);
return;
case 'quasiquote'
- ast = quasiquote(ast{2}); % TCO
+ ast = quasiquote(ast.get(2)); % TCO
case 'defmacro!'
- ret = env.set(ast{2}, EVAL(ast{3}, env));
+ ret = env.set(ast.get(2), EVAL(ast.get(3), env));
ret.is_macro = true;
return;
case 'macroexpand'
- ret = macroexpand(ast{2}, env);
+ ret = macroexpand(ast.get(2), env);
return;
case 'do'
- el = eval_ast(ast(2:end-1), env);
- ast = ast{end}; % TCO
+ el = eval_ast(ast.slice(2,length(ast)-1), env);
+ ast = ast.get(length(ast)); % TCO
case 'if'
- cond = EVAL(ast{2}, env);
+ cond = EVAL(ast.get(2), env);
if strcmp(class(cond), 'types.Nil') || ...
(islogical(cond) && cond == false)
if length(ast) > 3
- ast = ast{4}; % TCO
+ ast = ast.get(4); % TCO
else
ret = types.nil;
return;
end
else
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
end
case 'fn*'
- fn = @(varargin) EVAL(ast{3}, Env(env, ast{2}, varargin));
- ret = types.Function(fn, ast{3}, env, ast{2});
+ fn = @(varargin) EVAL(ast.get(3), Env(env, ast.get(2), ...
+ types.List(varargin{:})));
+ ret = types.Function(fn, ast.get(3), env, ast.get(2));
return;
otherwise
el = eval_ast(ast, env);
- f = el{1};
- args = el(2:end);
+ f = el.get(1);
+ args = el.slice(2);
if isa(f, 'types.Function')
env = Env(f.env, f.params, args);
ast = f.ast; % TCO
else
- ret = f(args{:});
+ ret = f(args.data{:});
return
end
end
repl_env.set(types.Symbol(k), ns(k));
end
repl_env.set(types.Symbol('eval'), @(a) EVAL(a, repl_env));
- repl_env.set(types.Symbol('*ARGV*'), args(2:end));
+ rest_args = args(2:end);
+ repl_env.set(types.Symbol('*ARGV*'), types.List(rest_args{:}));
% core.mal: defined using the langauge itself
rep('(def! not (fn* (a) (if a false true)))', repl_env);
% eval
function ret = is_pair(ast)
- ret = iscell(ast) && length(ast) > 0;
+ ret = types.sequential_Q(ast) && length(ast) > 0;
end
function ret = quasiquote(ast)
if ~is_pair(ast)
- ret = {types.Symbol('quote'), ast};
- elseif isa(ast{1},'types.Symbol') && ...
- strcmp(ast{1}.name, 'unquote')
- ret = ast{2};
- elseif is_pair(ast{1}) && isa(ast{1}{1},'types.Symbol') && ...
- strcmp(ast{1}{1}.name, 'splice-unquote')
- ret = {types.Symbol('concat'), ...
- ast{1}{2}, ...
- quasiquote(ast(2:end))};
+ ret = types.List(types.Symbol('quote'), ast);
+ elseif isa(ast.get(1),'types.Symbol') && ...
+ strcmp(ast.get(1).name, 'unquote')
+ ret = ast.get(2);
+ elseif is_pair(ast.get(1)) && ...
+ isa(ast.get(1).get(1),'types.Symbol') && ...
+ strcmp(ast.get(1).get(1).name, 'splice-unquote')
+ ret = types.List(types.Symbol('concat'), ...
+ ast.get(1).get(2), ...
+ quasiquote(ast.slice(2)));
else
- ret = {types.Symbol('cons'), ...
- quasiquote(ast{1}), ...
- quasiquote(ast(2:end))};
+ ret = types.List(types.Symbol('cons'), ...
+ quasiquote(ast.get(1)), ...
+ quasiquote(ast.slice(2)));
end
end
function ret = is_macro_call(ast, env)
- if iscell(ast) && isa(ast{1}, 'types.Symbol') && ...
- ~islogical(env.find(ast{1}))
- f = env.get(ast{1});
+ if types.list_Q(ast) && isa(ast.get(1), 'types.Symbol') && ...
+ ~islogical(env.find(ast.get(1)))
+ f = env.get(ast.get(1));
ret = isa(f,'types.Function') && f.is_macro;
else
ret = false;
function ret = macroexpand(ast, env)
while is_macro_call(ast, env)
- mac = env.get(ast{1});
- ast = mac.fn(ast{2:end});
+ mac = env.get(ast.get(1));
+ args = ast.slice(2);
+ ast = mac.fn(args.data{:});
end
ret = ast;
end
switch class(ast)
case 'types.Symbol'
ret = env.get(ast);
- case 'cell'
- ret = {};
+ case 'types.List'
+ ret = types.List();
for i=1:length(ast)
- ret{end+1} = EVAL(ast{i}, env);
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.Vector'
+ ret = types.Vector();
+ for i=1:length(ast)
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.HashMap'
+ ret = types.HashMap();
+ ks = ast.keys();
+ for i=1:length(ks)
+ k = ks{i};
+ ret.set(EVAL(k, env), EVAL(ast.get(k), env));
end
otherwise
ret = ast;
function ret = EVAL(ast, env)
while true
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = eval_ast(ast, env);
return;
end
% apply
ast = macroexpand(ast, env);
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = ast;
return;
end
- if isa(ast{1},'types.Symbol')
- a1sym = ast{1}.name;
+ if isa(ast.get(1),'types.Symbol')
+ a1sym = ast.get(1).name;
else
a1sym = '_@$fn$@_';
end
switch (a1sym)
case 'def!'
- ret = env.set(ast{2}, EVAL(ast{3}, env));
+ ret = env.set(ast.get(2), EVAL(ast.get(3), env));
return;
case 'let*'
let_env = Env(env);
- for i=1:2:length(ast{2})
- let_env.set(ast{2}{i}, EVAL(ast{2}{i+1}, let_env));
+ for i=1:2:length(ast.get(2))
+ let_env.set(ast.get(2).get(i), EVAL(ast.get(2).get(i+1), let_env));
end
env = let_env;
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
case 'quote'
- ret = ast{2};
+ ret = ast.get(2);
return;
case 'quasiquote'
- ast = quasiquote(ast{2}); % TCO
+ ast = quasiquote(ast.get(2)); % TCO
case 'defmacro!'
- ret = env.set(ast{2}, EVAL(ast{3}, env));
+ ret = env.set(ast.get(2), EVAL(ast.get(3), env));
ret.is_macro = true;
return;
case 'macroexpand'
- ret = macroexpand(ast{2}, env);
+ ret = macroexpand(ast.get(2), env);
return;
case 'try*'
try
- ret = EVAL(ast{2}, env);
+ ret = EVAL(ast.get(2), env);
return;
catch e
- if length(ast) > 2 && strcmp(ast{3}{1}.name, 'catch*')
+ if length(ast) > 2 && strcmp(ast.get(3).get(1).name, 'catch*')
if isa(e, 'types.MalException')
exc = e.obj;
else
exc = e.message;
end
- ret = EVAL(ast{3}{3}, Env(env, {ast{3}{2}}, {exc}));
+ catch_env = Env(env, types.List(ast.get(3).get(2)), ...
+ types.List(exc));
+ ret = EVAL(ast.get(3).get(3), catch_env);
return;
else
throw(e);
end
end
case 'do'
- el = eval_ast(ast(2:end-1), env);
- ast = ast{end}; % TCO
+ el = eval_ast(ast.slice(2,length(ast)-1), env);
+ ast = ast.get(length(ast)); % TCO
case 'if'
- cond = EVAL(ast{2}, env);
+ cond = EVAL(ast.get(2), env);
if strcmp(class(cond), 'types.Nil') || ...
(islogical(cond) && cond == false)
if length(ast) > 3
- ast = ast{4}; % TCO
+ ast = ast.get(4); % TCO
else
ret = types.nil;
return;
end
else
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
end
case 'fn*'
- fn = @(varargin) EVAL(ast{3}, Env(env, ast{2}, varargin));
- ret = types.Function(fn, ast{3}, env, ast{2});
+ fn = @(varargin) EVAL(ast.get(3), Env(env, ast.get(2), ...
+ types.List(varargin{:})));
+ ret = types.Function(fn, ast.get(3), env, ast.get(2));
return;
otherwise
el = eval_ast(ast, env);
- f = el{1};
- args = el(2:end);
+ f = el.get(1);
+ args = el.slice(2);
if isa(f, 'types.Function')
env = Env(f.env, f.params, args);
ast = f.ast; % TCO
else
- ret = f(args{:});
+ ret = f(args.data{:});
return
end
end
repl_env.set(types.Symbol(k), ns(k));
end
repl_env.set(types.Symbol('eval'), @(a) EVAL(a, repl_env));
- repl_env.set(types.Symbol('*ARGV*'), args(2:end));
+ rest_args = args(2:end);
+ repl_env.set(types.Symbol('*ARGV*'), types.List(rest_args{:}));
% core.mal: defined using the langauge itself
rep('(def! not (fn* (a) (if a false true)))', repl_env);
% eval
function ret = is_pair(ast)
- ret = iscell(ast) && length(ast) > 0;
+ ret = types.sequential_Q(ast) && length(ast) > 0;
end
function ret = quasiquote(ast)
if ~is_pair(ast)
- ret = {types.Symbol('quote'), ast};
- elseif isa(ast{1},'types.Symbol') && ...
- strcmp(ast{1}.name, 'unquote')
- ret = ast{2};
- elseif is_pair(ast{1}) && isa(ast{1}{1},'types.Symbol') && ...
- strcmp(ast{1}{1}.name, 'splice-unquote')
- ret = {types.Symbol('concat'), ...
- ast{1}{2}, ...
- quasiquote(ast(2:end))};
+ ret = types.List(types.Symbol('quote'), ast);
+ elseif isa(ast.get(1),'types.Symbol') && ...
+ strcmp(ast.get(1).name, 'unquote')
+ ret = ast.get(2);
+ elseif is_pair(ast.get(1)) && ...
+ isa(ast.get(1).get(1),'types.Symbol') && ...
+ strcmp(ast.get(1).get(1).name, 'splice-unquote')
+ ret = types.List(types.Symbol('concat'), ...
+ ast.get(1).get(2), ...
+ quasiquote(ast.slice(2)));
else
- ret = {types.Symbol('cons'), ...
- quasiquote(ast{1}), ...
- quasiquote(ast(2:end))};
+ ret = types.List(types.Symbol('cons'), ...
+ quasiquote(ast.get(1)), ...
+ quasiquote(ast.slice(2)));
end
end
function ret = is_macro_call(ast, env)
- if iscell(ast) && isa(ast{1}, 'types.Symbol') && ...
- ~islogical(env.find(ast{1}))
- f = env.get(ast{1});
+ if types.list_Q(ast) && isa(ast.get(1), 'types.Symbol') && ...
+ ~islogical(env.find(ast.get(1)))
+ f = env.get(ast.get(1));
ret = isa(f,'types.Function') && f.is_macro;
else
ret = false;
function ret = macroexpand(ast, env)
while is_macro_call(ast, env)
- mac = env.get(ast{1});
- ast = mac.fn(ast{2:end});
+ mac = env.get(ast.get(1));
+ args = ast.slice(2);
+ ast = mac.fn(args.data{:});
end
ret = ast;
end
switch class(ast)
case 'types.Symbol'
ret = env.get(ast);
- case 'cell'
- ret = {};
+ case 'types.List'
+ ret = types.List();
for i=1:length(ast)
- ret{end+1} = EVAL(ast{i}, env);
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.Vector'
+ ret = types.Vector();
+ for i=1:length(ast)
+ ret.append(EVAL(ast.get(i), env));
+ end
+ case 'types.HashMap'
+ ret = types.HashMap();
+ ks = ast.keys();
+ for i=1:length(ks)
+ k = ks{i};
+ ret.set(EVAL(k, env), EVAL(ast.get(k), env));
end
otherwise
ret = ast;
function ret = EVAL(ast, env)
while true
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = eval_ast(ast, env);
return;
end
% apply
ast = macroexpand(ast, env);
- if ~iscell(ast)
+ if ~types.list_Q(ast)
ret = ast;
return;
end
- if isa(ast{1},'types.Symbol')
- a1sym = ast{1}.name;
+ if isa(ast.get(1),'types.Symbol')
+ a1sym = ast.get(1).name;
else
a1sym = '_@$fn$@_';
end
switch (a1sym)
case 'def!'
- ret = env.set(ast{2}, EVAL(ast{3}, env));
+ ret = env.set(ast.get(2), EVAL(ast.get(3), env));
return;
case 'let*'
let_env = Env(env);
- for i=1:2:length(ast{2})
- let_env.set(ast{2}{i}, EVAL(ast{2}{i+1}, let_env));
+ for i=1:2:length(ast.get(2))
+ let_env.set(ast.get(2).get(i), EVAL(ast.get(2).get(i+1), let_env));
end
env = let_env;
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
case 'quote'
- ret = ast{2};
+ ret = ast.get(2);
return;
case 'quasiquote'
- ast = quasiquote(ast{2}); % TCO
+ ast = quasiquote(ast.get(2)); % TCO
case 'defmacro!'
- ret = env.set(ast{2}, EVAL(ast{3}, env));
+ ret = env.set(ast.get(2), EVAL(ast.get(3), env));
ret.is_macro = true;
return;
case 'macroexpand'
- ret = macroexpand(ast{2}, env);
+ ret = macroexpand(ast.get(2), env);
return;
case 'try*'
try
- ret = EVAL(ast{2}, env);
+ ret = EVAL(ast.get(2), env);
return;
catch e
- if length(ast) > 2 && strcmp(ast{3}{1}.name, 'catch*')
+ if length(ast) > 2 && strcmp(ast.get(3).get(1).name, 'catch*')
if isa(e, 'types.MalException')
exc = e.obj;
else
exc = e.message;
end
- ret = EVAL(ast{3}{3}, Env(env, {ast{3}{2}}, {exc}));
+ catch_env = Env(env, types.List(ast.get(3).get(2)), ...
+ types.List(exc));
+ ret = EVAL(ast.get(3).get(3), catch_env);
return;
else
throw(e);
end
end
case 'do'
- el = eval_ast(ast(2:end-1), env);
- ast = ast{end}; % TCO
+ el = eval_ast(ast.slice(2,length(ast)-1), env);
+ ast = ast.get(length(ast)); % TCO
case 'if'
- cond = EVAL(ast{2}, env);
+ cond = EVAL(ast.get(2), env);
if strcmp(class(cond), 'types.Nil') || ...
(islogical(cond) && cond == false)
if length(ast) > 3
- ast = ast{4}; % TCO
+ ast = ast.get(4); % TCO
else
ret = types.nil;
return;
end
else
- ast = ast{3}; % TCO
+ ast = ast.get(3); % TCO
end
case 'fn*'
- fn = @(varargin) EVAL(ast{3}, Env(env, ast{2}, varargin));
- ret = types.Function(fn, ast{3}, env, ast{2});
+ fn = @(varargin) EVAL(ast.get(3), Env(env, ast.get(2), ...
+ types.List(varargin{:})));
+ ret = types.Function(fn, ast.get(3), env, ast.get(2));
return;
otherwise
el = eval_ast(ast, env);
- f = el{1};
- args = el(2:end);
+ f = el.get(1);
+ args = el.slice(2);
if isa(f, 'types.Function')
env = Env(f.env, f.params, args);
ast = f.ast; % TCO
else
- ret = f(args{:});
+ ret = f(args.data{:});
return
end
end
repl_env.set(types.Symbol(k), ns(k));
end
repl_env.set(types.Symbol('eval'), @(a) EVAL(a, repl_env));
- repl_env.set(types.Symbol('*ARGV*'), args(2:end));
+ rest_args = args(2:end);
+ repl_env.set(types.Symbol('*ARGV*'), types.List(rest_args{:}));
% core.mal: defined using the langauge itself
rep('(def! *host-language* "matlab")', repl_env);
function ret = equal(a,b)
ret = false;
ota = class(a); otb = class(b);
- if ~(strcmp(ota,otb) || (iscell(a) && iscell(b)))
+ if ~(strcmp(ota,otb) || ...
+ (types.sequential_Q(a) && types.sequential_Q(b)))
return;
end
switch (ota)
- case 'cell'
+ case {'types.List', 'types.Vector'}
if ~(length(a) == length(b))
- return
+ return;
end
for i=1:length(a)
- if ~(types.equal(a{i}, b{i}))
- return
+ if ~(types.equal(a.get(i), b.get(i)))
+ return;
end
end
ret = true;
ret = a == b;
end
end
+
+ function ret = sequential_Q(obj)
+ ret = strcmp(class(obj), 'types.List') || ...
+ strcmp(class(obj), 'types.Vector');
+ end
+
+ function ret = list_Q(obj)
+ ret = strcmp(class(obj), 'types.List');
+ end
+ function ret = vector_Q(obj)
+ ret = strcmp(class(obj), 'types.Vector');
+ end
+ function ret = hash_map_Q(obj)
+ ret = strcmp(class(obj), 'types.HashMap');
+ end
+
+ function ret = keyword(str)
+ ret = strcat(native2unicode(hex2dec('029e'),'UTF-8'), ...
+ str(2:end));
+ end
+ function ret = keyword_Q(obj)
+ ret = length(obj) > 1 && ...
+ strcmp(obj(1), native2unicode(hex2dec('029e'),'UTF-8'));
+ end
end
end