|
| 1 | +/** |
| 2 | + * kin: mori + lisp + sweet.js |
| 3 | + * MIT license http://www.opensource.org/licenses/mit-license.php/ |
| 4 | + * Copyright (C) 2014 Luca Antiga http://lantiga.github.io |
| 5 | + */ |
| 6 | + |
| 7 | +macro _args { |
| 8 | + rule { ($arg) } => { |
| 9 | + _sexpr $arg |
| 10 | + } |
| 11 | + rule { ($arg $args ...) } => { |
| 12 | + _sexpr $arg, _args ($args ...) |
| 13 | + } |
| 14 | +} |
| 15 | + |
| 16 | +macro _fun { |
| 17 | + case { _ ($f) } => { |
| 18 | + var fun = unwrapSyntax(#{$f}); |
| 19 | + var mori_funs = { |
| 20 | + // Fundamentals |
| 21 | + equals: true, |
| 22 | + hash: true, |
| 23 | + // Type predicates |
| 24 | + is_list: true, |
| 25 | + is_seq: true, |
| 26 | + is_vector: true, |
| 27 | + is_map: true, |
| 28 | + is_set: true, |
| 29 | + is_collection: true, |
| 30 | + is_sequential: true, |
| 31 | + is_associative: true, |
| 32 | + is_counted: true, |
| 33 | + is_indexed: true, |
| 34 | + is_reduceable: true, |
| 35 | + is_seqable: true, |
| 36 | + is_reversible: true, |
| 37 | + // Collections |
| 38 | + list: true, |
| 39 | + vector: true, |
| 40 | + hash_map: true, |
| 41 | + set: true, |
| 42 | + sorted_set: true, |
| 43 | + range: true, |
| 44 | + // Collection operations |
| 45 | + conj: true, |
| 46 | + into: true, |
| 47 | + assoc: true, |
| 48 | + dissoc: true, |
| 49 | + empty: true, |
| 50 | + get: true, |
| 51 | + get_in: true, |
| 52 | + has_key: true, |
| 53 | + find: true, |
| 54 | + nth: true, |
| 55 | + last: true, |
| 56 | + assoc_in: true, |
| 57 | + update_in: true, |
| 58 | + count: true, |
| 59 | + is_empty: true, |
| 60 | + peek: true, |
| 61 | + pop: true, |
| 62 | + zipmap: true, |
| 63 | + reverse: true, |
| 64 | + // Vector operations |
| 65 | + subvec: true, |
| 66 | + // Hash map operations |
| 67 | + keys: true, |
| 68 | + vals: true, |
| 69 | + // Set operations |
| 70 | + disj: true, |
| 71 | + union: true, |
| 72 | + intersection: true, |
| 73 | + difference: true, |
| 74 | + is_subset: true, |
| 75 | + is_superset: true, |
| 76 | + // Sequences |
| 77 | + first: true, |
| 78 | + rest: true, |
| 79 | + seq: true, |
| 80 | + cons: true, |
| 81 | + concat: true, |
| 82 | + flatten: true, |
| 83 | + into_array: true, |
| 84 | + each: true, |
| 85 | + map: true, |
| 86 | + mapcat: true, |
| 87 | + filter: true, |
| 88 | + remove: true, |
| 89 | + reduce: true, |
| 90 | + reduce_kv: true, |
| 91 | + take: true, |
| 92 | + take_while: true, |
| 93 | + drop: true, |
| 94 | + drop_while: true, |
| 95 | + some: true, |
| 96 | + every: true, |
| 97 | + sort: true, |
| 98 | + sort_by: true, |
| 99 | + interpose: true, |
| 100 | + interleave: true, |
| 101 | + iterate: true, |
| 102 | + repeat: true, |
| 103 | + repeatedly: true, |
| 104 | + partition: true, |
| 105 | + partition_by: true, |
| 106 | + group_by: true, |
| 107 | + // Helpers |
| 108 | + prim_seq: true, |
| 109 | + identity: true, |
| 110 | + constantly: true, |
| 111 | + inc: true, |
| 112 | + dec: true, |
| 113 | + sum: true, |
| 114 | + is_even: true, |
| 115 | + is_odd: true, |
| 116 | + comp: true, |
| 117 | + juxt: true, |
| 118 | + knit: true, |
| 119 | + pipeline: true, |
| 120 | + partial: true, |
| 121 | + curry: true, |
| 122 | + fnil: true, |
| 123 | + js_to_clj: true, |
| 124 | + clj_to_js: true |
| 125 | + } |
| 126 | + if (mori_funs[fun]) { |
| 127 | + return #{mori.$f} |
| 128 | + } |
| 129 | + return #{$f} |
| 130 | + } |
| 131 | +} |
| 132 | + |
| 133 | +macro _keys { |
| 134 | + rule { ($($k $v)) } => { |
| 135 | + $k |
| 136 | + } |
| 137 | + rule { ($($k $v) $($ks $vs) ...) } => { |
| 138 | + $k, _keys ($($ks $vs) ...) |
| 139 | + } |
| 140 | +} |
| 141 | + |
| 142 | +macro _vals { |
| 143 | + rule { ($($k $v)) } => { |
| 144 | + $v |
| 145 | + } |
| 146 | + rule { ($($k $v) $($ks $vs) ...) } => { |
| 147 | + $v, _vals ($($ks $vs) ...) |
| 148 | + } |
| 149 | +} |
| 150 | + |
| 151 | +macro _sexpr { |
| 152 | + rule { () } => { |
| 153 | + } |
| 154 | + rule { (fn [$args ...] $sexprs ...) } => { |
| 155 | + function ($args(,)...) { |
| 156 | + _return_sexprs ($sexprs ...) |
| 157 | + } |
| 158 | + } |
| 159 | + //rule { (letv [$($k $v) ...] $sexprs ...) } => { |
| 160 | + // function ( _keys($($k $v) ...) ) { |
| 161 | + // _return_sexprs ($sexprs ...) |
| 162 | + // }(_vals ($($k $v) ...)) |
| 163 | + //} |
| 164 | + rule { (prn $args ...) } => { |
| 165 | + console.log(_sexprs($args ...)) |
| 166 | + } |
| 167 | + rule { (js $body ...) } => { |
| 168 | + $body ... |
| 169 | + } |
| 170 | + rule { ($f) } => { |
| 171 | + _fun($f)() |
| 172 | + } |
| 173 | + rule { ($f $arg) } => { |
| 174 | + _fun($f)(_args($arg)) |
| 175 | + } |
| 176 | + rule { ($f $arg $args ...) } => { |
| 177 | + _fun($f)( _args($arg) , _args($args ...)) |
| 178 | + } |
| 179 | + rule { $x } => { $x } |
| 180 | +} |
| 181 | + |
| 182 | +macro _return_sexprs { |
| 183 | + rule { ($sexpr) } => { |
| 184 | + return _sexpr $sexpr |
| 185 | + } |
| 186 | + rule { ($sexpr $sexprs ...) } => { |
| 187 | + _sexpr $sexpr _return_sexprs ($sexprs ...) |
| 188 | + } |
| 189 | +} |
| 190 | + |
| 191 | +macro _sexprs { |
| 192 | + rule { ($sexpr) } => { |
| 193 | + _sexpr $sexpr |
| 194 | + } |
| 195 | + rule { ($sexpr $sexprs ...) } => { |
| 196 | + _sexpr $sexpr _sexprs ($sexprs ...) |
| 197 | + } |
| 198 | +} |
| 199 | + |
| 200 | +macro kin { |
| 201 | + rule { ($x ...) } => { |
| 202 | + _sexpr ($x ...) |
| 203 | + } |
| 204 | +} |
| 205 | + |
| 206 | +// EXAMPLES |
| 207 | + |
| 208 | +var mori = require('mori'); |
| 209 | + |
| 210 | +// Mori at your fingertips |
| 211 | +var foo = kin (vector 1 2 3) |
| 212 | +kin (conj foo 4) |
| 213 | +// => [1 2 3 4] |
| 214 | + |
| 215 | +// Plus lambdas |
| 216 | +kin (map (fn [a] (inc a)) (range 5)) |
| 217 | +// => (1 2 3 4 5) |
| 218 | + |
| 219 | +// Interoperability: write js in a kin form |
| 220 | +var fn1 = kin (js function (a,b) { return a + b + 2; }) |
| 221 | + |
| 222 | +// at any level - e.g. you can use infix where it makes sense |
| 223 | +var fn2 = kin (fn [a b] (js a + b + 2)) |
| 224 | + |
| 225 | +// and you can use kin wherever in js code |
| 226 | +function somefunc (a) { |
| 227 | + kin (clj_to_js (filter (fn [el] (is_even el)) (range a))).forEach(function(el) { |
| 228 | + console.log(el); |
| 229 | + }); |
| 230 | + return [0, 1, 2, 3, 4].filter(kin (fn [el] (is_even el))); |
| 231 | +} |
| 232 | +console.log(somefunc(5)); |
| 233 | + |
| 234 | +// Like a pro |
| 235 | +kin (take 6 (map (fn [x] (js x * 2)) (range 1000))) |
| 236 | +// => (0 2 4 6 8 10) |
| 237 | + |
| 238 | + |
| 239 | +// TODO: |
| 240 | +// * letv (impl. above doesn't work due to parsing quirks) |
| 241 | +// * literals |
| 242 | +// * math expressions -> use infix (SOLVED) |
| 243 | +// * destructuring |
| 244 | +// * threading macros |
| 245 | + |
| 246 | + |
0 commit comments