1 // Node vs browser behavior
3 if (typeof module
=== 'undefined') {
6 var types
= require('./types'),
7 readline
= require('./node_readline'),
8 reader
= require('./reader'),
9 printer
= require('./printer'),
10 interop
= require('./interop');
14 function mal_throw(exc
) { throw exc
; }
19 return Array
.prototype.map
.call(arguments
,function(exp
) {
20 return printer
._pr_str(exp
, true);
25 return Array
.prototype.map
.call(arguments
,function(exp
) {
26 return printer
._pr_str(exp
, false);
31 printer
.println
.apply({}, Array
.prototype.map
.call(arguments
,function(exp
) {
32 return printer
._pr_str(exp
, true);
37 printer
.println
.apply({}, Array
.prototype.map
.call(arguments
,function(exp
) {
38 return printer
._pr_str(exp
, false);
43 if (typeof require
!== 'undefined') {
44 return require('fs').readFileSync(f
, 'utf-8');
46 var req
= new XMLHttpRequest();
47 req
.open("GET", f
, false);
49 if (req
.status
== 200) {
50 return req
.responseText
;
52 throw new Error("Failed to slurp file: " + f
);
59 function time_ms() { return new Date().getTime(); }
63 function assoc(src_hm
) {
64 var hm
= types
._clone(src_hm
);
65 var args
= [hm
].concat(Array
.prototype.slice
.call(arguments
, 1));
66 return types
._assoc_BANG
.apply(null, args
);
69 function dissoc(src_hm
) {
70 var hm
= types
._clone(src_hm
);
71 var args
= [hm
].concat(Array
.prototype.slice
.call(arguments
, 1));
72 return types
._dissoc_BANG
.apply(null, args
);
75 function get(hm
, key
) {
76 if (hm
!= null && key
in hm
) {
83 function contains_Q(hm
, key
) {
84 if (key
in hm
) { return true; } else { return false; }
87 function keys(hm
) { return Object
.keys(hm
); }
88 function vals(hm
) { return Object
.keys(hm
).map(function(k
) { return hm
[k
]; }); }
92 function cons(a
, b
) { return [a
].concat(b
); }
94 function concat(lst
) {
96 return lst
.concat
.apply(lst
, Array
.prototype.slice
.call(arguments
, 1));
99 function nth(lst
, idx
) {
100 if (idx
< lst
.length
) { return lst
[idx
]; }
101 else { throw new Error("nth: index out of range"); }
104 function first(lst
) { return (lst
=== null) ? null : lst
[0]; }
106 function rest(lst
) { return (lst
== null) ? [] : lst
.slice(1); }
108 function empty_Q(lst
) { return lst
.length
=== 0; }
111 if (Array
.isArray(s
)) { return s
.length
; }
112 else if (s
=== null) { return 0; }
113 else { return Object
.keys(s
).length
; }
117 if (types
._list_Q(lst
)) {
118 return Array
.prototype.slice
.call(arguments
, 1).reverse().concat(lst
);
120 var v
= lst
.concat(Array
.prototype.slice
.call(arguments
, 1));
121 v
.__isvector__
= true;
127 if (types
._list_Q(obj
)) {
128 return obj
.length
> 0 ? obj
: null;
129 } else if (types
._vector_Q(obj
)) {
130 return obj
.length
> 0 ? Array
.prototype.slice
.call(obj
, 0): null;
131 } else if (types
._string_Q(obj
)) {
132 return obj
.length
> 0 ? obj
.split('') : null;
133 } else if (obj
=== null) {
136 throw new Error("seq: called on non-sequence");
142 var args
= Array
.prototype.slice
.call(arguments
, 1);
143 return f
.apply(f
, args
.slice(0, args
.length
-1).concat(args
[args
.length
-1]));
146 function map(f
, lst
) {
147 return lst
.map(function(el
){ return f(el
); });
151 // Metadata functions
152 function with_meta(obj
, m
) {
153 var new_obj
= types
._clone(obj
);
154 new_obj
.__meta__
= m
;
159 // TODO: support symbols and atoms
160 if ((!types
._sequential_Q(obj
)) &&
161 (!(types
._hash_map_Q(obj
))) &&
162 (!(types
._function_Q(obj
)))) {
163 throw new Error("attempt to get metadata from: " + types
._obj_type(obj
));
170 function deref(atm
) { return atm
.val
; }
171 function reset_BANG(atm
, val
) { return atm
.val
= val
; }
172 function swap_BANG(atm
, f
) {
173 var args
= [atm
.val
].concat(Array
.prototype.slice
.call(arguments
, 2));
174 atm
.val
= f
.apply(f
, args
);
178 function js_eval(str
) {
179 return interop
.js_to_mal(eval(str
.toString()));
182 function js_method_call(object_method_str
) {
183 var args
= Array
.prototype.slice
.call(arguments
, 1),
184 r
= interop
.resolve_js(object_method_str
),
185 obj
= r
[0], f
= r
[1];
186 var res
= f
.apply(obj
, args
);
187 return interop
.js_to_mal(res
);
190 // types.ns is namespace of type functions
191 var ns
= {'type': types
._obj_type
,
194 'nil?': types
._nil_Q
,
195 'true?': types
._true_Q
,
196 'false?': types
._false_Q
,
197 'number?': types
._number_Q
,
198 'string?': types
._string_Q
,
199 'symbol': types
._symbol
,
200 'symbol?': types
._symbol_Q
,
201 'keyword': types
._keyword
,
202 'keyword?': types
._keyword_Q
,
204 'macro?': types
._macro_Q
,
210 'readline': readline
.readline
,
211 'read-string': reader
.read_str
,
213 '<' : function(a
,b
){return a
<b
;},
214 '<=' : function(a
,b
){return a
<=b
;},
215 '>' : function(a
,b
){return a
>b
;},
216 '>=' : function(a
,b
){return a
>=b
;},
217 '+' : function(a
,b
){return a
+b
;},
218 '-' : function(a
,b
){return a
-b
;},
219 '*' : function(a
,b
){return a
*b
;},
220 '/' : function(a
,b
){return a
/b
;},
224 'list?': types
._list_Q
,
225 'vector': types
._vector
,
226 'vector?': types
._vector_Q
,
227 'hash-map': types
._hash_map
,
228 'map?': types
._hash_map_Q
,
232 'contains?': contains_Q
,
236 'sequential?': types
._sequential_Q
,
250 'with-meta': with_meta
,
253 'atom?': types
._atom_Q
,
255 "reset!": reset_BANG
,
262 exports
.ns
= core
.ns
= ns
;