Merge branch 'master' into issue_166_string_ops
[jackhill/mal.git] / es6 / core.js
CommitLineData
afa79313
JM
1import { _equal_Q, _clone, _list_Q, _sequential_Q,
2 _keyword, _keyword_Q, _vector, _vector_Q,
3 _hash_map, _hash_map_Q, _assoc_BANG, _dissoc_BANG,
4f8c7db9
JM
4 _symbol, _symbol_Q, Atom } from './types'
5import { pr_str } from './printer'
6import { readline } from './node_readline'
7import { read_str } from './reader'
5024b694 8
1db28cde
JM
9// Errors/Exceptions
10function mal_throw(exc) { throw exc; }
11
5024b694 12// String functions
73bd649f
JM
13function slurp(f) {
14 if (typeof require !== 'undefined') {
4f8c7db9 15 return require('fs').readFileSync(f, 'utf-8')
73bd649f 16 } else {
4f8c7db9
JM
17 var req = new XMLHttpRequest()
18 req.open('GET', f, false)
19 req.send()
73bd649f 20 if (req.status == 200) {
4f8c7db9 21 return req.responseText
73bd649f 22 } else {
4f8c7db9 23 throw new Error(`Failed to slurp file: ${f}`)
73bd649f
JM
24 }
25 }
26}
27
28// Sequence functions
1db28cde
JM
29function nth(lst, idx) {
30 if (idx < lst.length) { return lst[idx]; }
4f8c7db9 31 else { throw new Error('nth: index out of range'); }
73bd649f 32}
5024b694 33
e5c4e656 34function conj(lst, ...args) {
afa79313 35 if (_list_Q(lst)) {
4f8c7db9 36 return args.reverse().concat(lst)
afa79313 37 } else {
4f8c7db9 38 return _vector(...lst.concat(args))
afa79313
JM
39 }
40}
41
4c14a8b8
JM
42function seq(obj) {
43 if (_list_Q(obj)) {
44 return obj.length > 0 ? obj : null
45 } else if (_vector_Q(obj)) {
46 return obj.length > 0 ? obj.slice(0) : null
47 } else if (typeof obj === "string" && obj[0] !== '\u029e') {
48 return obj.length > 0 ? obj.split('') : null
49 } else if (obj === null) {
50 return null
51 } else {
52 throw new Error('seq: called on non-sequence')
53 }
54}
55
56// hash-map functions
57
afa79313 58function keys(hm) {
4f8c7db9
JM
59 // TODO: Array.from(hm.keys()) when supported
60 let ks = []
61 for (let k of hm.keys()) { ks.push(k) }
62 return ks
afa79313
JM
63}
64
65function vals(hm) {
4f8c7db9
JM
66 // TODO: Array.from(hm.keys()) when supported
67 let vs = []
68 for (let v of hm.values()) { vs.push(v) }
69 return vs
e5c4e656
JM
70}
71
72// Metadata functions
e5c4e656 73function with_meta(obj, m) {
4f8c7db9
JM
74 let new_obj = _clone(obj)
75 new_obj.meta = m
76 return new_obj
e5c4e656
JM
77}
78
1db28cde 79// core_ns is namespace of type functions
5024b694 80export const core_ns = new Map([
1db28cde
JM
81 ['=', _equal_Q],
82 ['throw', mal_throw],
afa79313 83
1db28cde
JM
84 ['nil?', a => a === null],
85 ['true?', a => a === true],
86 ['false?', a => a === false],
4c14a8b8 87 ['string?', a => typeof a === "string" && a[0] !== '\u029e'],
4f8c7db9
JM
88 ['symbol', a => _symbol(a)],
89 ['symbol?', a => _symbol_Q(a)],
afa79313
JM
90 ['keyword', a => _keyword(a)],
91 ['keyword?', a => _keyword_Q(a)],
5024b694 92
4f8c7db9
JM
93 ['pr-str', (...a) => a.map(e => pr_str(e,1)).join(' ')],
94 ['str', (...a) => a.map(e => pr_str(e,0)).join('')],
95 ['prn', (...a) => console.log(...a.map(e => pr_str(e,1))) || null],
96 ['println', (...a) => console.log(...a.map(e => pr_str(e,0))) || null],
e5c4e656
JM
97 ['read-string', read_str],
98 ['readline', readline],
73bd649f 99 ['slurp', slurp],
5024b694
JM
100
101 ['<' , (a,b) => a<b],
102 ['<=', (a,b) => a<=b],
103 ['>' , (a,b) => a>b],
104 ['>=', (a,b) => a>=b],
105 ['+' , (a,b) => a+b],
106 ['-' , (a,b) => a-b],
107 ['*' , (a,b) => a*b],
108 ['/' , (a,b) => a/b],
109 ["time-ms", () => new Date().getTime()],
110
111 ['list', (...a) => a],
1db28cde 112 ['list?', _list_Q],
afa79313
JM
113 ['vector', _vector],
114 ['vector?', _vector_Q],
115 ['hash-map', _hash_map],
116 ['map?', _hash_map_Q],
117 ['assoc', (m,...a) => _assoc_BANG(_clone(m), ...a)],
118 ['dissoc', (m,...a) => _dissoc_BANG(_clone(m), ...a)],
119 ['get', (m,a) => m === null ? null : m.has(a) ? m.get(a) : null],
120 ['contains?', (m,a) => m.has(a)],
121 ['keys', keys],
122 ['vals', vals],
123
124 ['sequential?', _sequential_Q],
73bd649f
JM
125 ['cons', (a,b) => [a].concat(b)],
126 ['concat', (...a) => a.reduce((x,y) => x.concat(y), [])],
1db28cde 127 ['nth', nth],
8d1e25ac
DM
128 ['first', a => a !== null && a.length > 0 ? a[0] : null],
129 ['rest', a => a === null ? [] : a.slice(1)],
5024b694 130 ['empty?', a => a.length === 0],
1db28cde
JM
131 ['count', a => a === null ? 0 : a.length],
132 ['apply', (f,...a) => f(...a.slice(0, -1).concat(a[a.length-1]))],
e5c4e656
JM
133 ['map', (f,a) => a.map(x => f(x))],
134
135 ['conj', conj],
4c14a8b8 136 ['seq', seq],
e5c4e656 137
4f8c7db9 138 ['meta', a => 'meta' in a ? a['meta'] : null],
e5c4e656
JM
139 ['with-meta', with_meta],
140 ['atom', a => new Atom(a)],
141 ['atom?', a => a instanceof Atom],
142 ['deref', atm => atm.val],
143 ['reset!', (atm,a) => atm.val = a],
afa79313 144 ['swap!', (atm,f,...args) => atm.val = f(...[atm.val].concat(args))]
4f8c7db9 145 ])