matlab: start of step4
authorJoel Martin <github@martintribe.org>
Sun, 8 Feb 2015 07:13:41 +0000 (01:13 -0600)
committerJoel Martin <github@martintribe.org>
Mon, 9 Feb 2015 05:51:08 +0000 (23:51 -0600)
matlab/+types/Nil.m [new file with mode: 0644]
matlab/Env.m
matlab/core.m [new file with mode: 0644]
matlab/printer.m
matlab/reader.m
matlab/step4_if_fn_do.m [new file with mode: 0644]
matlab/types.m [new file with mode: 0644]

diff --git a/matlab/+types/Nil.m b/matlab/+types/Nil.m
new file mode 100644 (file)
index 0000000..d7573f0
--- /dev/null
@@ -0,0 +1,2 @@
+classdef Nil
+end
index 1d080a3..1a7b3fc 100644 (file)
@@ -4,10 +4,24 @@ classdef Env < handle
         outer
     end
     methods
-        function env = Env(outer)
+        function env = Env(outer, binds, exprs)
             env.data = containers.Map();
             env.outer = outer;
+
+            if nargin > 1
+                env = Env(outer);
+                for i=1:length(binds)
+                    k = binds{i}.name;
+                    if strcmp(k, '&')
+                        env.data(binds{i+1}.name) = exprs(i:end);
+                        break;
+                    else
+                        env.data(k) = exprs{i};
+                    end
+                end
+            end
         end
+
         function ret = set(env, k, v)
             env.data(k.name) = v;
             ret = v;
diff --git a/matlab/core.m b/matlab/core.m
new file mode 100644 (file)
index 0000000..968b9a4
--- /dev/null
@@ -0,0 +1,22 @@
+classdef core
+    methods(Static)
+        function n = ns()
+            n = containers.Map();
+            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) a*b;
+            n('/') = @(a,b) floor(a/b);
+
+            n('list') = @(varargin) varargin;
+            n('list?') = @iscell;
+            n('empty?') = @(a) length(a) == 0;
+            n('count') = @(a) length(a);
+        end
+    end
+end
+
index b164093..9308a96 100644 (file)
@@ -13,6 +13,8 @@ classdef printer
                 strs = cellfun(@(x) printer.pr_str(x, print_readably), ...
                                obj, 'UniformOutput', false);
                 str = strcat('(', strjoin(strs, ' '), ')');
+            case 'types.Nil'
+                str = 'nil';
             case 'logical'
                 if eq(obj, true)
                     str = 'true';
index 8c752c9..77dae07 100644 (file)
@@ -14,7 +14,8 @@ classdef reader
                 atm = str2double(token);
             elseif strcmp(token(1), '"')
                 atm = token(2:length(token)-1);
-            %else if token eq 'nil'
+            elseif strcmp(token, 'nil')
+                atm = types.nil;
             elseif strcmp(token, 'true')
                 atm = true;
             elseif strcmp(token, 'false')
diff --git a/matlab/step4_if_fn_do.m b/matlab/step4_if_fn_do.m
new file mode 100644 (file)
index 0000000..4f73da7
--- /dev/null
@@ -0,0 +1,98 @@
+function step4_if_fn_do(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);
+    case 'do'
+        el = eval_ast(ast(2:end), env);
+        ret = el{end};
+    case 'if'
+        cond = EVAL(ast{2}, env);
+        if strcmp(class(cond), 'types.Nil') || ...
+           (islogical(cond) && cond == false)
+           if length(ast) > 3
+                ret = EVAL(ast{4}, env);
+            else
+                ret = types.nil;
+            end
+        else
+            ret = EVAL(ast{3}, env);
+        end
+    case 'fn*'
+        ret = @(varargin) EVAL(ast{3}, Env(env, ast{2}, varargin));
+    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);
+    ns = core.ns(); ks = ns.keys();
+    for i=1:length(ks)
+        k = ks{i};
+        repl_env.set(types.Symbol(k), ns(k));
+    end
+
+    %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
diff --git a/matlab/types.m b/matlab/types.m
new file mode 100644 (file)
index 0000000..cb3bf8f
--- /dev/null
@@ -0,0 +1,6 @@
+classdef types
+    properties (Constant = true)
+        nil = types.Nil();
+    end
+end
+