@bablr/agast-helpers 0.10.10 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/debug.js ADDED
@@ -0,0 +1,39 @@
1
+ import { TagPath } from '@bablr/agast-helpers/path';
2
+ import { printTag } from '@bablr/agast-helpers/print';
3
+ import { CloseNodeTag, LiteralTag, OpenNodeTag } from '@bablr/agast-helpers/symbols';
4
+
5
+ export { printTag };
6
+
7
+ export const printTree = (tree) => {
8
+ let printed = '';
9
+ let unshift = false;
10
+ let tagPath = TagPath.fromNode(tree, 0);
11
+
12
+ let count = 0;
13
+
14
+ do {
15
+ if (tagPath.type === CloseNodeTag) count--;
16
+
17
+ printed += '\n' + ' '.repeat(count) + printTag(tagPath.tag);
18
+
19
+ if (tagPath.type === OpenNodeTag && !tagPath.value.selfClosing) count++;
20
+ } while ((tagPath = unshift ? tagPath.nextUnshifted : tagPath.next));
21
+
22
+ return printed;
23
+ };
24
+
25
+ export const printTreeSource = (tree) => {
26
+ let printed = '';
27
+ let unshift = false;
28
+ let tagPath = TagPath.fromNode(tree, 0);
29
+
30
+ do {
31
+ if (tagPath.type === LiteralTag) {
32
+ printed += tagPath.value;
33
+ } else if (tagPath.type === OpenNodeTag && tagPath.value.literalValue) {
34
+ printed += tagPath.value.literalValue;
35
+ }
36
+ } while ((tagPath = unshift ? tagPath.nextUnshifted : tagPath.next));
37
+
38
+ return printed;
39
+ };
@@ -0,0 +1,5 @@
1
+ import { printTag, printTree, printTreeSource } from './debug.js';
2
+
3
+ globalThis.printTag = printTag;
4
+ globalThis.printTree = printTree;
5
+ globalThis.printTreeSource = printTreeSource;
@@ -0,0 +1,170 @@
1
+ import {
2
+ continue_,
3
+ getStreamIterator,
4
+ StreamGenerator,
5
+ StreamIterable,
6
+ wait,
7
+ } from '@bablr/stream-iterator';
8
+
9
+ let { getPrototypeOf } = Object;
10
+ let { isArray } = Array;
11
+
12
+ export const maybeWait = (maybePromise, callback) => {
13
+ if (maybePromise instanceof Promise) {
14
+ return maybePromise.then(callback);
15
+ } else {
16
+ return callback(maybePromise);
17
+ }
18
+ };
19
+
20
+ function* __concat(iterables) {
21
+ for (const iterable of iterables) {
22
+ let iter = getStreamIterator(iterable);
23
+ let step;
24
+
25
+ for (;;) {
26
+ step = iter.next();
27
+ while (step === null || step instanceof Promise) {
28
+ if (step === null) yield continue_(), (step = iter.next());
29
+ if (step instanceof Promise) step = yield wait(step);
30
+ }
31
+ if (step.done) break;
32
+
33
+ yield step.value;
34
+ }
35
+ }
36
+ }
37
+
38
+ export const concat = (...iterables) => {
39
+ return new StreamIterable(__concat(iterables));
40
+ };
41
+
42
+ function* __reduce(reducer, values, initial) {
43
+ let acc = initial;
44
+ let iter = getStreamIterator(values);
45
+ let step;
46
+
47
+ for (;;) {
48
+ step = iter.next();
49
+ while (step === null || step instanceof Promise) {
50
+ if (step === null) yield continue_(), (step = iter.next());
51
+ if (step instanceof Promise) step = yield wait(step);
52
+ }
53
+ if (step.done) break;
54
+
55
+ let { value } = step;
56
+
57
+ acc = reducer(acc, value);
58
+ }
59
+
60
+ return acc;
61
+ }
62
+
63
+ export const reduce = (reducer, value, initial) => {
64
+ let iter = new StreamGenerator(__reduce(reducer, value, initial));
65
+
66
+ return maybeWait(iter.next(), (step) => step.value);
67
+ };
68
+
69
+ function* __isEmpty(iterable) {
70
+ let iter = getStreamIterator(iterable);
71
+ let step;
72
+
73
+ for (;;) {
74
+ step = iter.next();
75
+ while (step === null || step instanceof Promise) {
76
+ if (step === null) yield continue_(), (step = iter.next());
77
+ if (step instanceof Promise) step = yield wait(step);
78
+ }
79
+ if (step.done) break;
80
+
81
+ return false;
82
+ }
83
+
84
+ return true;
85
+ }
86
+
87
+ export const isEmpty = (iterable) => {
88
+ if (iterable == null) return true;
89
+ let iter = new StreamGenerator(__isEmpty(iterable));
90
+
91
+ return maybeWait(iter.next(), (step) => step.value);
92
+ };
93
+
94
+ function* __map(fn, iterable) {
95
+ let iter = getStreamIterator(iterable);
96
+ let step;
97
+
98
+ for (;;) {
99
+ step = iter.next();
100
+ while (step === null || step instanceof Promise) {
101
+ if (step === null) yield continue_(), (step = iter.next());
102
+ if (step instanceof Promise) step = yield wait(step);
103
+ }
104
+ if (step.done) break;
105
+
106
+ let value = fn(step.value);
107
+
108
+ if (value instanceof Promise) {
109
+ value = yield wait(value);
110
+ }
111
+
112
+ yield value;
113
+ }
114
+ }
115
+
116
+ export const map = (fn, iterable) => {
117
+ return new StreamIterable(__map(fn, iterable));
118
+ };
119
+
120
+ function* __flatMap(fn, tags) {
121
+ let iter = getStreamIterator(tags);
122
+ let step;
123
+
124
+ for (;;) {
125
+ step = iter.next();
126
+ while (step === null || step instanceof Promise) {
127
+ if (step === null) yield continue_(), (step = iter.next());
128
+ if (step instanceof Promise) step = yield wait(step);
129
+ }
130
+ if (step.done) break;
131
+
132
+ let { value } = step;
133
+
134
+ yield* fn(value);
135
+ }
136
+
137
+ return true;
138
+ }
139
+
140
+ export const flatMap = (fn, tags) => new StreamIterable(__flatMap(fn, tags));
141
+
142
+ function* __arrayValues(arr) {
143
+ let { length } = arr;
144
+ for (let i = 0; i < length; i++) yield arr[i];
145
+ }
146
+
147
+ export const arrayValues = (arr) => {
148
+ let proto = getPrototypeOf(arr);
149
+ return proto === Array.prototype ? arr[Symbol.iterator]() : __arrayValues(arr);
150
+ };
151
+
152
+ function* __wrap(iterable) {
153
+ let iter = getStreamIterator(iterable);
154
+ let step;
155
+
156
+ for (;;) {
157
+ step = iter.next();
158
+ while (step === null || step instanceof Promise) {
159
+ if (step === null) yield continue_(), (step = iter.next());
160
+ if (step instanceof Promise) step = yield wait(step);
161
+ }
162
+ if (step.done) break;
163
+
164
+ yield step.value;
165
+ }
166
+ }
167
+
168
+ export const wrap = (iterable) => {
169
+ return isArray(iterable) ? arrayValues(iterable) : new StreamIterable(__wrap(iterable));
170
+ };
package/lib/object.js CHANGED
@@ -1,10 +1,28 @@
1
+ import { wrap } from './iterable.js';
2
+
1
3
  export const { hasOwn, freeze, isFrozen, seal, isSealed, getPrototypeOf, getOwnPropertySymbols } =
2
4
  Object;
3
5
  export const { isArray } = Array;
4
6
 
7
+ export { deepFreezeRecord, isDeepRecord, isRecord, recordValues } from '@bablr/record';
8
+
9
+ let { setPrototypeOf } = Object;
10
+
11
+ export const freezeRecord = (obj) => {
12
+ setPrototypeOf(obj, null);
13
+ freeze(obj);
14
+ return obj;
15
+ };
16
+
17
+ export const freezeClass = (constructor) => {
18
+ freeze(constructor);
19
+ freeze(constructor.prototype);
20
+ return constructor;
21
+ };
22
+
5
23
  export const has = (obj, path) => {
6
24
  let value = obj;
7
- for (const part of path) {
25
+ for (const part of wrap(path)) {
8
26
  if (!hasOwn(value, part)) return false;
9
27
  value = value[part];
10
28
  }
@@ -13,7 +31,7 @@ export const has = (obj, path) => {
13
31
 
14
32
  export const get = (obj, path) => {
15
33
  let value = obj;
16
- for (const part of path) {
34
+ for (const part of wrap(path)) {
17
35
  value = value[part];
18
36
  }
19
37
  return value;
@@ -69,13 +87,42 @@ export const immSet = (obj, path, value) => {
69
87
  obj_ = objs[i];
70
88
  obj_ = isArray(obj_) ? [...obj_] : { ...obj_ };
71
89
  obj_[path[i]] = newValue;
72
- freeze(obj_);
90
+ freezeRecord(obj_);
73
91
  newValue = obj_;
74
92
  }
75
93
 
76
94
  return obj_;
77
95
  };
78
96
 
97
+ const emptyIterator = {
98
+ next() {
99
+ return { value: undefined, done: true };
100
+ },
101
+ };
102
+
103
+ const emptySpreadable = Object.freeze(
104
+ Object.create({
105
+ [Symbol.iterator]() {
106
+ return emptyIterator;
107
+ },
108
+ }),
109
+ );
110
+
111
+ export const when = (condition, value) => {
112
+ const valueType = typeof value;
113
+ if (
114
+ !(value == null || value[Symbol.iterator] || valueType === 'object' || valueType === 'function')
115
+ ) {
116
+ throw new Error('Second argument to when must be an object, iterable, or function.');
117
+ }
118
+
119
+ return condition && value != null
120
+ ? valueType === 'function'
121
+ ? value()
122
+ : value
123
+ : emptySpreadable;
124
+ };
125
+
79
126
  export const isObject = (obj) => obj !== null && typeof obj === 'object';
80
127
  export const isPlainObject = (val) => val && [Object.prototype, null].includes(getPrototypeOf(val));
81
128
  export const isFunction = (obj) => typeof obj === 'function';
@@ -84,3 +131,5 @@ export const isString = (obj) => typeof obj === 'string';
84
131
  export const isType = (obj) => isSymbol(obj) || isString(obj);
85
132
  export const isRegex = (obj) => obj instanceof RegExp;
86
133
  export const isPattern = (obj) => isString(obj) || isRegex(obj);
134
+
135
+ export const arrayLast = (arr) => arr[arr.length - 1];
package/lib/parse.js ADDED
@@ -0,0 +1,30 @@
1
+ import { isObject } from './object.js';
2
+
3
+ export const buildParser = (str) => {
4
+ return isObject(str) ? str : { idx: 0, str };
5
+ };
6
+
7
+ export const inRange = (value, lower, upper) => value >= lower && value <= upper;
8
+
9
+ let refChrs = ['.', '#', '@', '_', '`'];
10
+
11
+ export const canStartIdentifier = (chr) => {
12
+ return (
13
+ inRange(chr, 'a', 'z') ||
14
+ inRange(chr, 'A', 'Z') ||
15
+ refChrs.includes(chr) ||
16
+ inRange(chr, '\u0080', '\u{10ffff}')
17
+ );
18
+ };
19
+
20
+ export const match = (p, literal) => {
21
+ let idx = 0;
22
+ let endIdx = literal.length;
23
+ let { idx: pIdx, str } = p;
24
+
25
+ while (idx < endIdx) {
26
+ if (str[pIdx + idx] !== literal[idx]) return null;
27
+ idx++;
28
+ }
29
+ return literal;
30
+ };