diff options
Diffstat (limited to 'js/core.js')
| -rw-r--r-- | js/core.js | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/js/core.js b/js/core.js new file mode 100644 index 0000000..48bbe16 --- /dev/null +++ b/js/core.js @@ -0,0 +1,193 @@ +// Node vs browser behavior +var core = {}; +if (typeof module === 'undefined') { + var exports = core; +} else { + var types = require('./types'), + printer = require('./printer'); +} + +// Errors/Exceptions +function mal_throw(exc) { throw exc; } + + +// String functions +function pr_str() { + return Array.prototype.map.call(arguments,function(exp) { + return printer._pr_str(exp, true); + }).join(" "); +} + +function str() { + return Array.prototype.map.call(arguments,function(exp) { + return printer._pr_str(exp, false); + }).join(""); +} + +function prn() { + printer.print.apply({}, Array.prototype.map.call(arguments,function(exp) { + return printer._pr_str(exp, true); + })); +} + +function println() { + printer.print.apply({}, Array.prototype.map.call(arguments,function(exp) { + return printer._pr_str(exp, false); + })); +} + + +// Hash Map functions +function assoc(src_hm) { + var hm = types._clone(src_hm); + var args = [hm].concat(Array.prototype.slice.call(arguments, 1)); + return types._assoc_BANG.apply(null, args); +} + +function dissoc(src_hm) { + var hm = types._clone(src_hm); + var args = [hm].concat(Array.prototype.slice.call(arguments, 1)); + return types._dissoc_BANG.apply(null, args); +} + +function get(hm, key) { + if (key in hm) { + return hm[key]; + } else { + return null; + } +} + +function contains_Q(hm, key) { + if (key in hm) { return true; } else { return false; } +} + +function keys(hm) { return Object.keys(hm); } +function vals(hm) { return Object.keys(hm).map(function(k) { return hm[k]; }); } + + +// Sequence functions +function cons(a, b) { return [a].concat(b); } + +function concat(lst) { + lst = lst || []; + return lst.concat.apply(lst, Array.prototype.slice.call(arguments, 1)); +} + +function nth(lst, idx) { return lst[idx]; } + +function first(lst) { return lst[0]; } + +function rest(lst) { return lst.slice(1); } + +function empty_Q(lst) { return lst.length === 0; } + +function count(s) { + if (Array.isArray(s)) { return s.length; } + else { return Object.keys(s).length; } +} + +function conj(lst) { + if (types._list_Q(lst)) { + return Array.prototype.slice.call(arguments, 1).reverse().concat(lst); + } else { + var v = lst.concat(Array.prototype.slice.call(arguments, 1)); + v.__isvector__ = true; + return v; + } +} + +function apply(f) { + var args = Array.prototype.slice.call(arguments, 1); + return f.apply(f, args.slice(0, args.length-1).concat(args[args.length-1])); +} + +function map(f, lst) { + return lst.map(function(el){ return f(el); }); +} + + +// Metadata functions +function with_meta(obj, m) { + var new_obj = types._clone(obj); + new_obj.__meta__ = m; + return new_obj; +} + +function meta(obj) { + // TODO: support symbols and atoms + if ((!types._sequential_Q(obj)) && + (!(types._hash_map_Q(obj))) && + (!(types._function_Q(obj)))) { + throw new Error("attempt to get metadata from: " + types._obj_type(obj)); + } + return obj.__meta__; +} + + +// Atom functions +function deref(atm) { return atm.val; } +function reset_BANG(atm, val) { return atm.val = val; } +function swap_BANG(atm, f) { + var args = [atm.val].concat(Array.prototype.slice.call(arguments, 2)); + atm.val = f.apply(f, args); + return atm.val; +} + + +// types.ns is namespace of type functions +var ns = {'type': types._obj_type, + '=': types._equal_Q, + 'throw': mal_throw, + 'nil?': types._nil_Q, + 'true?': types._true_Q, + 'false?': types._false_Q, + 'symbol': types._symbol, + 'symbol?': types._symbol_Q, + 'pr-str': pr_str, + 'str': str, + 'prn': prn, + 'println': println, + '<' : function(a,b){return a<b;}, + '<=' : function(a,b){return a<=b;}, + '>' : function(a,b){return a>b;}, + '>=' : function(a,b){return a>=b;}, + '+' : function(a,b){return a+b;}, + '-' : function(a,b){return a-b;}, + '*' : function(a,b){return a*b;}, + '/' : function(a,b){return a/b;}, + + 'list': types._list, + 'list?': types._list_Q, + 'vector': types._vector, + 'vector?': types._vector_Q, + 'hash-map': types._hash_map, + 'map?': types._hash_map_Q, + 'assoc': assoc, + 'dissoc': dissoc, + 'get': get, + 'contains?': contains_Q, + 'keys': keys, + 'vals': vals, + + 'sequential?': types._sequential_Q, + 'cons': cons, + 'concat': concat, + 'nth': nth, + 'first': first, + 'rest': rest, + 'empty?': empty_Q, + 'count': count, + 'conj': conj, + 'apply': apply, + 'map': map, + + 'with-meta': with_meta, + 'meta': meta, + 'atom': types._atom, + 'atom?': types._atom_Q, + "deref": deref, + "reset!": reset_BANG, + "swap!": swap_BANG}; + +exports.ns = core.ns = ns; |
