1 if (typeof module
!== 'undefined') {
2 var types
= require('./types');
3 var readline
= require('./node_readline');
4 var reader
= require('./reader');
5 var printer
= require('./printer');
6 var Env
= require('./env').Env
;
7 var core
= require('./core');
12 return reader
.read_str(str
);
17 return types
._sequential_Q(x
) && x
.length
> 0;
20 function quasiquote(ast
) {
22 return [types
._symbol("quote"), ast
];
23 } else if (ast
[0].value
=== 'unquote') {
25 } else if (is_pair(ast
[0]) && ast
[0][0].value
=== 'splice-unquote') {
26 return [types
._symbol("concat"),
28 quasiquote(ast
.slice(1))];
30 return [types
._symbol("cons"),
32 quasiquote(ast
.slice(1))];
36 function is_macro_call(ast
, env
) {
37 return types
._list_Q(ast
) &&
38 types
._symbol_Q(ast
[0]) &&
39 env
.find(ast
[0].value
) &&
40 env
.get(ast
[0].value
)._ismacro_
;
43 function macroexpand(ast
, env
) {
44 while (is_macro_call(ast
, env
)) {
45 var mac
= env
.get(ast
[0]);
46 ast
= mac
.apply(mac
, ast
.slice(1));
51 function eval_ast(ast
, env
) {
52 if (types
._symbol_Q(ast
)) {
54 } else if (types
._list_Q(ast
)) {
55 return ast
.map(function(a
) { return EVAL(a
, env
); });
56 } else if (types
._vector_Q(ast
)) {
57 var v
= ast
.map(function(a
) { return EVAL(a
, env
); });
58 v
.__isvector__
= true;
60 } else if (types
._hash_map_Q(ast
)) {
63 new_hm
[EVAL(k
, env
)] = EVAL(ast
[k
], env
);
71 function _EVAL(ast
, env
) {
74 //printer.println("EVAL:", types._pr_str(ast, true));
75 if (!types
._list_Q(ast
)) {
76 return eval_ast(ast
, env
);
80 ast
= macroexpand(ast
, env
);
81 if (!types
._list_Q(ast
)) { return ast
; }
83 var a0
= ast
[0], a1
= ast
[1], a2
= ast
[2], a3
= ast
[3];
86 var res
= EVAL(a2
, env
);
87 return env
.set(a1
, res
);
89 var let_env
= new Env(env
);
90 for (var i
=0; i
< a1
.length
; i
+=2) {
91 let_env
.set(a1
[i
].value
, EVAL(a1
[i
+1], let_env
));
93 return EVAL(a2
, let_env
);
97 return EVAL(quasiquote(a1
), env
);
99 var func
= EVAL(a2
, env
);
100 func
._ismacro_
= true;
101 return env
.set(a1
, func
);
103 return macroexpand(a1
, env
);
105 return eval(a1
.toString());
107 var el
= eval_ast(ast
.slice(2), env
),
108 f
= eval(a1
.toString());
109 return f
.apply(f
, el
);
111 eval_ast(ast
.slice(1, -1), env
);
112 ast
= ast
[ast
.length
-1];
115 var cond
= EVAL(a1
, env
);
116 if (cond
=== null || cond
=== false) {
117 ast
= (typeof a3
!== "undefined") ? a3
: null;
123 return types
._function(EVAL
, Env
, a2
, env
, a1
);
125 var el
= eval_ast(ast
, env
), f
= el
[0];
128 env
= f
.__gen_env__(el
.slice(1));
130 return f
.apply(f
, el
.slice(1));
137 function EVAL(ast
, env
) {
138 var result
= _EVAL(ast
, env
);
139 return (typeof result
!== "undefined") ? result
: null;
143 function PRINT(exp
) {
144 return printer
._pr_str(exp
, true);
148 var repl_env
= new Env();
149 var rep = function(str
) { return PRINT(EVAL(READ(str
), repl_env
)); };
150 _ref = function (k
,v
) { repl_env
.set(k
, v
); }
152 // Import core functions
153 for (var n
in core
.ns
) { repl_env
.set(n
, core
.ns
[n
]); }
155 _ref('read-string', reader
.read_str
);
156 _ref('eval', function(ast
) { return EVAL(ast
, repl_env
); });
157 _ref('slurp', function(f
) {
158 return require('fs').readFileSync(f
, 'utf-8');
161 // Defined using the language itself
162 rep("(def! not (fn* (a) (if a false true)))");
163 rep("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))");
165 if (typeof process
!== 'undefined' && process
.argv
.length
> 2) {
166 for (var i
=2; i
< process
.argv
.length
; i
++) {
167 rep('(load-file "' + process
.argv
[i
] + '")');
169 } else if (typeof require
=== 'undefined') {
170 // Asynchronous browser mode
171 readline
.rlwrap(function(line
) { return rep(line
); },
173 if (exc
instanceof reader
.BlankException
) { return; }
174 if (exc
.stack
) { printer
.println(exc
.stack
); }
175 else { printer
.println(exc
); }
177 } else if (require
.main
=== module
) {
178 // Synchronous node.js commandline mode
180 var line
= readline
.readline("user> ");
181 if (line
=== null) { break; }
183 if (line
) { printer
.println(rep(line
)); }
185 if (exc
instanceof reader
.BlankException
) { continue; }
186 if (exc
.stack
) { printer
.println(exc
.stack
); }
187 else { printer
.println(exc
); }