UNPKG

4.63 kBJavaScriptView Raw
1'use strict'
2
3const {TokenTypeData} = require('./lang');
4const {chain, or, and} = require('./frontend');
5
6function isEmpty(obj) {
7 return obj.size().eq(0)
8}
9
10function getIn(obj, path) {
11 const pathGetters = [obj].concat(path.map((_part, index) => path.slice(0, index + 1).reduce((acc, part) => acc.get(part), obj)))
12 return and(...pathGetters);
13}
14
15function has(obj, key) {
16 return obj.get(key).isUndefined().not()
17}
18
19function assignIn(obj, args) {
20 return chain([
21 obj,
22 ...args
23 ]).assign();
24}
25
26function reduce(collection, predicate, initialValue) {
27 return collection.size().eq(0).ternary(
28 initialValue,
29 collection.recursiveMap((loop, value, index) =>
30 predicate(index.eq(0).ternary(
31 initialValue, index.minus(1).recur(loop)), value, index))
32 .get(collection.size().minus(1)))
33}
34
35function concat(a, b) {
36 return chain([a, b]).flatten()
37}
38
39function uniq(arr) {
40 return arr
41 .keyBy(x => x)
42 .keys()
43}
44
45function intersection(a, b) {
46 const array = a.uniq().concat(b.uniq())
47
48 return array
49 .keyBy((_, idx) => idx)
50 .groupBy(val => val)
51 .filterBy(val => val.keys().size().gt(1))
52 .keys()
53}
54
55function find(collection, predicate, givenCtx) {
56 return collection.values().filter((val, key, ctx) => predicate(val, key, ctx), givenCtx || null).get(0)
57}
58
59function join(arr, separator) {
60 return reduce(arr, (acc, value, index) => index.eq(0).ternary(acc.plus(value), acc.plus(separator).plus(value)), '')
61}
62
63function append(arr, value) {
64 return chain([arr, [value]]).flatten()
65 //return arr.size().plus(1).range().map(v => v.lt(arr.size()).ternary(arr.get(v), value))
66}
67
68function simpleSet(base, key, value) {
69 return chain([base, {[key]: value}]).assign()
70}
71
72function setIn(obj, path, value) {
73 if (!Array.isArray(path) || path.length === 0) {
74 throw new Error('only set with array paths');
75 }
76 path.forEach(val => {
77 if (typeof val !== 'string') {
78 throw new Error('all path parts in set should be strings');
79 }
80 })
81
82
83 const currentValues = path.map((part, index) =>
84 or(getIn(obj, path.slice(0, index)), chain({}))
85 )
86
87 return path.reduceRight((acc, part, index) => simpleSet(currentValues[index], part, acc), value)
88}
89
90function head(array) {
91 return array.get(0)
92}
93
94function last(array) {
95 return array.get(array.size().minus(1))
96}
97
98function reverse(array) {
99 return array.map((item, index) => array.get(array.size().minus(index.plus(1))))
100}
101
102function includesValue(collection, val) {
103 if (typeof val === 'boolean' || typeof val === 'number' || typeof val === 'string') {
104 return collection.anyValues((item, key, ctx) => item.eq(val))
105 }
106 return collection.anyValues((item, key, ctx) => item.eq(ctx), val)
107}
108
109function includes(collection, val) {
110 if (typeof val === 'boolean' || typeof val === 'number' || typeof val === 'string') {
111 return collection.any((item, key, ctx) => item.eq(val))
112 }
113 return collection.any((item, key, ctx) => item.eq(ctx), val)
114}
115
116function findIndex(collection, predicate) {
117 const filtered = collection.map((item, index) => predicate(item, index).ternary(index, chain(-1))).filter(item => item.gt(-1));
118 return filtered.size().ternary(
119 filtered.get(0),
120 -1
121 );
122}
123
124function pick(obj, arr) {
125 const projection = Object.assign({}, ...arr.map(key => ({[key]: obj.get(key)})));
126 return chain(projection).filterBy(item => item.isUndefined().not());
127}
128
129function every(array, predicate) {
130 return array.any((val, key, context) => predicate(val, key, context).not()).not()
131}
132
133function compact(array) {
134 return array.filter(value => value)
135}
136
137function switchCase(obj, caseTuples, defaultCase) {
138 return (caseTuples || []).reduce(
139 (result, caseTuple) => obj.eq(caseTuple[0]).ternary(
140 caseTuple[1],
141 result
142 ),
143 defaultCase || chain(null)
144 )
145}
146
147function conditionalTrace(obj, condition) {
148 return condition.ternary(
149 obj.trace(),
150 obj
151 )
152}
153
154function conditionalBreakpoint(obj, condition) {
155 return condition.ternary(
156 obj.breakpoint(),
157 obj
158 )
159}
160
161function tapTrace(obj, tapFn) {
162 return or(tapFn(obj).trace().ternary(chain(false), chain(false)), obj)
163}
164
165const sugarApi = {
166 getIn,
167 includes,
168 isEmpty,
169 assignIn,
170 reduce,
171 uniq,
172 intersection,
173 concat,
174 find,
175 join,
176 append,
177 setIn,
178 pick,
179 findIndex,
180 includesValue,
181 has,
182 reverse,
183 last,
184 head,
185 every,
186 simpleSet,
187 compact,
188 switch: switchCase,
189 conditionalTrace,
190 conditionalBreakpoint,
191 tapTrace
192};
193
194Object.keys(sugarApi).forEach(key => {
195 if (TokenTypeData[key]) {
196 throw new Error(`There is a builtin token with this sugar name ${key}`);
197 }
198});
199
200module.exports = sugarApi;