aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--matlab/Env.m36
-rw-r--r--matlab/step2_eval.m10
-rw-r--r--matlab/step3_env.m80
3 files changed, 122 insertions, 4 deletions
diff --git a/matlab/Env.m b/matlab/Env.m
new file mode 100644
index 0000000..1d080a3
--- /dev/null
+++ b/matlab/Env.m
@@ -0,0 +1,36 @@
+classdef Env < handle
+ properties
+ data
+ outer
+ end
+ methods
+ function env = Env(outer)
+ env.data = containers.Map();
+ env.outer = outer;
+ end
+ function ret = set(env, k, v)
+ env.data(k.name) = v;
+ ret = v;
+ end
+ function ret = find(env, k)
+ if env.data.isKey(k.name)
+ ret = env;
+ else
+ if ~islogical(env.outer)
+ ret = env.outer.find(k);
+ else
+ ret = false;
+ end
+ end
+ end
+ function ret = get(env, k)
+ fenv = env.find(k);
+ if ~islogical(fenv)
+ ret = fenv.data(k.name);
+ else
+ throw(MException('ENV:notfound', ...
+ strcat('''', k.name, ''' not found')));
+ end
+ end
+ end
+end
diff --git a/matlab/step2_eval.m b/matlab/step2_eval.m
index 418bb84..4ce13fb 100644
--- a/matlab/step2_eval.m
+++ b/matlab/step2_eval.m
@@ -1,4 +1,4 @@
-function step1_read_print(varargin), main(varargin), end
+function step2_eval(varargin), main(varargin), end
% read
function ret = READ(str)
@@ -44,9 +44,11 @@ function ret = rep(str, env)
end
function main(args)
- repl_env = containers.Map( ...
- {'+', '-', '*', '/'}, ...
- {@(a,b) a+b, @(a,b) a-b, @(a,b) a*b, @(a,b) floor(a/b)});
+ repl_env = containers.Map();
+ repl_env('+') = @(a,b) a+b;
+ repl_env('-') = @(a,b) a-b;
+ repl_env('*') = @(a,b) a*b;
+ repl_env('/') = @(a,b) floor(a/b);
%cleanObj = onCleanup(@() disp('*** here1 ***'));
while (true)
diff --git a/matlab/step3_env.m b/matlab/step3_env.m
new file mode 100644
index 0000000..6ac6426
--- /dev/null
+++ b/matlab/step3_env.m
@@ -0,0 +1,80 @@
+function step3_env(varargin), main(varargin), end
+
+% read
+function ret = READ(str)
+ ret = reader.read_str(str);
+end
+
+% eval
+function ret = eval_ast(ast, env)
+ switch class(ast)
+ case 'types.Symbol'
+ ret = env.get(ast);
+ case 'cell'
+ ret = {};
+ for i=1:length(ast)
+ ret{end+1} = EVAL(ast{i}, env);
+ end
+ otherwise
+ ret = ast;
+ end
+end
+
+function ret = EVAL(ast, env)
+ if ~iscell(ast),
+ ret = eval_ast(ast, env);
+ return;
+ end
+
+ % apply
+ if isa(ast{1},'types.Symbol')
+ a1sym = ast{1}.name;
+ else
+ a1sym = '_@$fn$@_';
+ end
+ switch (a1sym)
+ case 'def!'
+ ret = env.set(ast{2}, EVAL(ast{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));
+ end
+ ret = EVAL(ast{3}, let_env);
+ otherwise
+ el = eval_ast(ast, env);
+ f = el{1};
+ args = el(2:end);
+ ret = f(args{:});
+ end
+end
+
+% print
+function ret = PRINT(ast)
+ ret = printer.pr_str(ast, true);
+end
+
+% REPL
+function ret = rep(str, env)
+ ret = PRINT(EVAL(READ(str), env));
+end
+
+function main(args)
+ repl_env = Env(false);
+ repl_env.set(types.Symbol('+'), @(a,b) a+b);
+ repl_env.set(types.Symbol('-'), @(a,b) a-b);
+ repl_env.set(types.Symbol('*'), @(a,b) a*b);
+ repl_env.set(types.Symbol('/'), @(a,b) floor(a/b));
+
+ %cleanObj = onCleanup(@() disp('*** here1 ***'));
+ while (true)
+ line = input('user> ', 's');
+ if strcmp(strtrim(line),''), continue, end
+ try
+ fprintf('%s\n', rep(line, repl_env));
+ catch err
+ fprintf('Error: %s\n', err.message);
+ fprintf('%s\n', getReport(err, 'extended'));
+ end
+ end
+end