Commit | Line | Data |
---|---|---|
afa79313 JM |
1 | import { _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' |
5 | import { pr_str } from './printer' | |
6 | import { readline } from './node_readline' | |
7 | import { read_str } from './reader' | |
5024b694 | 8 | |
1db28cde JM |
9 | // Errors/Exceptions |
10 | function mal_throw(exc) { throw exc; } | |
11 | ||
5024b694 | 12 | // String functions |
73bd649f JM |
13 | function 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 |
29 | function 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 | 34 | function 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 |
42 | function 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 | 58 | function 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 | ||
65 | function 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 | 73 | function 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 | 80 | export 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 | ]) |