2015-08-02 06:29:44 +03:00
|
|
|
import { _equal_Q, _clone, _list_Q, _sequential_Q,
|
|
|
|
_keyword, _keyword_Q, _vector, _vector_Q,
|
|
|
|
_hash_map, _hash_map_Q, _assoc_BANG, _dissoc_BANG,
|
2015-08-05 06:20:58 +03:00
|
|
|
_symbol, _symbol_Q, Atom } from './types'
|
|
|
|
import { pr_str } from './printer'
|
|
|
|
import { readline } from './node_readline'
|
|
|
|
import { read_str } from './reader'
|
2015-07-31 07:57:45 +03:00
|
|
|
|
2015-08-01 04:53:59 +03:00
|
|
|
// Errors/Exceptions
|
|
|
|
function mal_throw(exc) { throw exc; }
|
|
|
|
|
2015-07-31 07:57:45 +03:00
|
|
|
// String functions
|
2015-07-31 08:29:44 +03:00
|
|
|
function slurp(f) {
|
|
|
|
if (typeof require !== 'undefined') {
|
2015-08-05 06:20:58 +03:00
|
|
|
return require('fs').readFileSync(f, 'utf-8')
|
2015-07-31 08:29:44 +03:00
|
|
|
} else {
|
2015-08-05 06:20:58 +03:00
|
|
|
var req = new XMLHttpRequest()
|
|
|
|
req.open('GET', f, false)
|
|
|
|
req.send()
|
2015-07-31 08:29:44 +03:00
|
|
|
if (req.status == 200) {
|
2015-08-05 06:20:58 +03:00
|
|
|
return req.responseText
|
2015-07-31 08:29:44 +03:00
|
|
|
} else {
|
2015-08-05 06:20:58 +03:00
|
|
|
throw new Error(`Failed to slurp file: ${f}`)
|
2015-07-31 08:29:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sequence functions
|
2015-08-01 04:53:59 +03:00
|
|
|
function nth(lst, idx) {
|
|
|
|
if (idx < lst.length) { return lst[idx]; }
|
2015-08-05 06:20:58 +03:00
|
|
|
else { throw new Error('nth: index out of range'); }
|
2015-07-31 08:29:44 +03:00
|
|
|
}
|
2015-07-31 07:57:45 +03:00
|
|
|
|
2015-08-01 07:08:33 +03:00
|
|
|
function conj(lst, ...args) {
|
2015-08-02 06:29:44 +03:00
|
|
|
if (_list_Q(lst)) {
|
2015-08-05 06:20:58 +03:00
|
|
|
return args.reverse().concat(lst)
|
2015-08-02 06:29:44 +03:00
|
|
|
} else {
|
2015-08-05 06:20:58 +03:00
|
|
|
return _vector(...lst.concat(args))
|
2015-08-02 06:29:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 18:18:46 +03:00
|
|
|
function seq(obj) {
|
|
|
|
if (_list_Q(obj)) {
|
|
|
|
return obj.length > 0 ? obj : null
|
|
|
|
} else if (_vector_Q(obj)) {
|
|
|
|
return obj.length > 0 ? obj.slice(0) : null
|
|
|
|
} else if (typeof obj === "string" && obj[0] !== '\u029e') {
|
|
|
|
return obj.length > 0 ? obj.split('') : null
|
|
|
|
} else if (obj === null) {
|
|
|
|
return null
|
|
|
|
} else {
|
|
|
|
throw new Error('seq: called on non-sequence')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// hash-map functions
|
|
|
|
|
2015-08-02 06:29:44 +03:00
|
|
|
function keys(hm) {
|
2015-08-05 06:20:58 +03:00
|
|
|
// TODO: Array.from(hm.keys()) when supported
|
|
|
|
let ks = []
|
|
|
|
for (let k of hm.keys()) { ks.push(k) }
|
|
|
|
return ks
|
2015-08-02 06:29:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function vals(hm) {
|
2015-08-05 06:20:58 +03:00
|
|
|
// TODO: Array.from(hm.keys()) when supported
|
|
|
|
let vs = []
|
|
|
|
for (let v of hm.values()) { vs.push(v) }
|
|
|
|
return vs
|
2015-08-01 07:08:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Metadata functions
|
|
|
|
function with_meta(obj, m) {
|
2015-08-05 06:20:58 +03:00
|
|
|
let new_obj = _clone(obj)
|
|
|
|
new_obj.meta = m
|
|
|
|
return new_obj
|
2015-08-01 07:08:33 +03:00
|
|
|
}
|
|
|
|
|
2015-08-01 04:53:59 +03:00
|
|
|
// core_ns is namespace of type functions
|
2015-07-31 07:57:45 +03:00
|
|
|
export const core_ns = new Map([
|
2015-08-01 04:53:59 +03:00
|
|
|
['=', _equal_Q],
|
|
|
|
['throw', mal_throw],
|
2015-08-02 06:29:44 +03:00
|
|
|
|
2015-08-01 04:53:59 +03:00
|
|
|
['nil?', a => a === null],
|
|
|
|
['true?', a => a === true],
|
|
|
|
['false?', a => a === false],
|
2016-02-11 18:18:46 +03:00
|
|
|
['string?', a => typeof a === "string" && a[0] !== '\u029e'],
|
2015-08-05 06:20:58 +03:00
|
|
|
['symbol', a => _symbol(a)],
|
|
|
|
['symbol?', a => _symbol_Q(a)],
|
2015-08-02 06:29:44 +03:00
|
|
|
['keyword', a => _keyword(a)],
|
|
|
|
['keyword?', a => _keyword_Q(a)],
|
2015-07-31 07:57:45 +03:00
|
|
|
|
2015-08-05 06:20:58 +03:00
|
|
|
['pr-str', (...a) => a.map(e => pr_str(e,1)).join(' ')],
|
|
|
|
['str', (...a) => a.map(e => pr_str(e,0)).join('')],
|
|
|
|
['prn', (...a) => console.log(...a.map(e => pr_str(e,1))) || null],
|
|
|
|
['println', (...a) => console.log(...a.map(e => pr_str(e,0))) || null],
|
2015-08-01 07:08:33 +03:00
|
|
|
['read-string', read_str],
|
|
|
|
['readline', readline],
|
2015-07-31 08:29:44 +03:00
|
|
|
['slurp', slurp],
|
2015-07-31 07:57:45 +03:00
|
|
|
|
|
|
|
['<' , (a,b) => a<b],
|
|
|
|
['<=', (a,b) => a<=b],
|
|
|
|
['>' , (a,b) => a>b],
|
|
|
|
['>=', (a,b) => a>=b],
|
|
|
|
['+' , (a,b) => a+b],
|
|
|
|
['-' , (a,b) => a-b],
|
|
|
|
['*' , (a,b) => a*b],
|
|
|
|
['/' , (a,b) => a/b],
|
|
|
|
["time-ms", () => new Date().getTime()],
|
|
|
|
|
|
|
|
['list', (...a) => a],
|
2015-08-01 04:53:59 +03:00
|
|
|
['list?', _list_Q],
|
2015-08-02 06:29:44 +03:00
|
|
|
['vector', _vector],
|
|
|
|
['vector?', _vector_Q],
|
|
|
|
['hash-map', _hash_map],
|
|
|
|
['map?', _hash_map_Q],
|
|
|
|
['assoc', (m,...a) => _assoc_BANG(_clone(m), ...a)],
|
|
|
|
['dissoc', (m,...a) => _dissoc_BANG(_clone(m), ...a)],
|
|
|
|
['get', (m,a) => m === null ? null : m.has(a) ? m.get(a) : null],
|
|
|
|
['contains?', (m,a) => m.has(a)],
|
|
|
|
['keys', keys],
|
|
|
|
['vals', vals],
|
|
|
|
|
|
|
|
['sequential?', _sequential_Q],
|
2015-07-31 08:29:44 +03:00
|
|
|
['cons', (a,b) => [a].concat(b)],
|
|
|
|
['concat', (...a) => a.reduce((x,y) => x.concat(y), [])],
|
2015-08-01 04:53:59 +03:00
|
|
|
['nth', nth],
|
2016-01-29 05:36:44 +03:00
|
|
|
['first', a => a !== null && a.length > 0 ? a[0] : null],
|
|
|
|
['rest', a => a === null ? [] : a.slice(1)],
|
2015-07-31 07:57:45 +03:00
|
|
|
['empty?', a => a.length === 0],
|
2015-08-01 04:53:59 +03:00
|
|
|
['count', a => a === null ? 0 : a.length],
|
|
|
|
['apply', (f,...a) => f(...a.slice(0, -1).concat(a[a.length-1]))],
|
2015-08-01 07:08:33 +03:00
|
|
|
['map', (f,a) => a.map(x => f(x))],
|
|
|
|
|
|
|
|
['conj', conj],
|
2016-02-11 18:18:46 +03:00
|
|
|
['seq', seq],
|
2015-08-01 07:08:33 +03:00
|
|
|
|
2015-08-05 06:20:58 +03:00
|
|
|
['meta', a => 'meta' in a ? a['meta'] : null],
|
2015-08-01 07:08:33 +03:00
|
|
|
['with-meta', with_meta],
|
|
|
|
['atom', a => new Atom(a)],
|
|
|
|
['atom?', a => a instanceof Atom],
|
|
|
|
['deref', atm => atm.val],
|
|
|
|
['reset!', (atm,a) => atm.val = a],
|
2015-08-02 06:29:44 +03:00
|
|
|
['swap!', (atm,f,...args) => atm.val = f(...[atm.val].concat(args))]
|
2015-08-05 06:20:58 +03:00
|
|
|
])
|