@cirru/parser.ts 0.0.8 → 0.0.10

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/src/tree.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ICirruNode } from "./types";
1
+ import type { ICirruNode } from "./types";
2
2
 
3
3
  export let pushToList = <T>(acc: T[], xs: T[], ys?: T[], zs?: T[]) => {
4
4
  let result = acc;
@@ -26,18 +26,16 @@ export let isNumber = (x: any) => typeof x === "number";
26
26
  export let isOdd = (x: number) => x % 2 === 1;
27
27
 
28
28
  export let resolveComma = (xs: ICirruNode[]) => {
29
- if (isEmpty(xs)) {
29
+ if (xs.length === 0) {
30
30
  return [];
31
31
  } else {
32
- return commaHelper(xs);
32
+ return commaHelper(xs, 0);
33
33
  }
34
34
  };
35
35
 
36
- let commaHelper = (intialAfter: ICirruNode[]) => {
36
+ let commaHelper = (after: ICirruNode[], start: number): ICirruNode[] => {
37
37
  let before: ICirruNode[] = [];
38
- let after: ICirruNode[] = intialAfter;
39
-
40
- let pointer = 0;
38
+ let pointer = start;
41
39
 
42
40
  while (true) {
43
41
  if (pointer >= after.length) {
@@ -45,16 +43,18 @@ let commaHelper = (intialAfter: ICirruNode[]) => {
45
43
  }
46
44
  let cursor = after[pointer];
47
45
 
48
- if (isArray(cursor) && notEmpty(cursor)) {
46
+ if (isArray(cursor) && cursor.length > 0) {
49
47
  let head = cursor[0];
50
48
  if (isArray(head)) {
51
- before.push(resolveComma(cursor));
49
+ before.push(commaHelper(cursor, 0));
52
50
  pointer += 1;
53
51
  } else if (head === ",") {
54
- pushToList(before, resolveComma(cursor.slice(1)));
52
+ // spread comma-expanded tail into before without a slice allocation
53
+ const expanded = commaHelper(cursor, 1);
54
+ for (let i = 0; i < expanded.length; i++) before.push(expanded[i]);
55
55
  pointer += 1;
56
56
  } else {
57
- before.push(resolveComma(cursor));
57
+ before.push(commaHelper(cursor, 0));
58
58
  pointer += 1;
59
59
  }
60
60
  } else {
@@ -65,35 +65,75 @@ let commaHelper = (intialAfter: ICirruNode[]) => {
65
65
  };
66
66
 
67
67
  export let resolveDollar = (xs: ICirruNode[]) => {
68
- if (isEmpty(xs)) {
68
+ if (xs.length === 0) {
69
69
  return [];
70
70
  } else {
71
- return dollarHelper(xs);
71
+ return dollarHelper(xs, 0);
72
72
  }
73
73
  };
74
74
 
75
- let dollarHelper = (initialAfter: ICirruNode[]) => {
76
- let before: ICirruNode[] = [];
77
- let after: ICirruNode[] = initialAfter;
75
+ // Combined pass intended to be equivalent to `resolveComma(resolveDollar(xs))`.
76
+ // Correctness matters more than speed here, so keep the logic structurally close
77
+ // to the existing two helpers and validate with explicit edge-case tests.
78
+ export let resolveDollarComma = (xs: ICirruNode[]) => {
79
+ if (xs.length === 0) {
80
+ return [];
81
+ } else {
82
+ return dollarCommaHelper(xs, 0);
83
+ }
84
+ };
78
85
 
79
- let pointer = 0;
86
+ // Pass `start` to avoid `after.slice(pointer + 1)` allocation on every `$` token.
87
+ let dollarHelper = (after: ICirruNode[], start: number): ICirruNode[] => {
88
+ let before: ICirruNode[] = [];
89
+ let pointer = start;
80
90
 
81
91
  while (true) {
82
92
  if (pointer >= after.length) {
83
93
  return before;
94
+ }
95
+ let cursor = after[pointer];
96
+
97
+ if (isArray(cursor)) {
98
+ before.push(dollarHelper(cursor, 0));
99
+ pointer += 1;
100
+ } else if (cursor === "$") {
101
+ before.push(dollarHelper(after, pointer + 1)); // no slice needed — pass bounds
102
+ break;
84
103
  } else {
85
- let cursor = after[pointer];
104
+ before.push(cursor);
105
+ pointer += 1;
106
+ }
107
+ }
108
+ return before;
109
+ };
86
110
 
87
- if (isArray(cursor)) {
88
- before.push(resolveDollar(cursor));
89
- pointer += 1;
90
- } else if (cursor === "$") {
91
- before.push(resolveDollar(after.slice(pointer + 1))); // pick items after pointer for $
92
- pointer = after.length; // trying to exit
111
+ let dollarCommaHelper = (after: ICirruNode[], start: number): ICirruNode[] => {
112
+ let before: ICirruNode[] = [];
113
+ let pointer = start;
114
+
115
+ while (true) {
116
+ if (pointer >= after.length) {
117
+ return before;
118
+ }
119
+ let cursor = after[pointer];
120
+
121
+ if (isArray(cursor)) {
122
+ const child = dollarCommaHelper(cursor, 0);
123
+ if (child.length > 0 && child[0] === ",") {
124
+ for (let i = 1; i < child.length; i++) before.push(child[i]);
93
125
  } else {
94
- before.push(cursor);
95
- pointer += 1;
126
+ before.push(child);
96
127
  }
128
+ pointer += 1;
129
+ } else if (cursor === "$") {
130
+ before.push(dollarCommaHelper(after, pointer + 1));
131
+ break;
132
+ } else {
133
+ before.push(cursor);
134
+ pointer += 1;
97
135
  }
98
136
  }
137
+
138
+ return before;
99
139
  };
@@ -19,5 +19,5 @@
19
19
  ]
20
20
  },
21
21
  "include": ["src/*.ts", "src/*/*.ts"],
22
- "exclude": ["src/*.test.ts"]
22
+ "exclude": ["src/*.test.ts", "src/bench.ts"]
23
23
  }
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "./tsconfig-compile.json",
3
+ "compilerOptions": {
4
+ "types": ["node"],
5
+ "target": "es2022",
6
+ "lib": ["es2022"],
7
+ "skipLibCheck": true
8
+ },
9
+ "include": ["src/bench.ts", "src/index.ts", "src/tree.ts", "src/types.ts"],
10
+ "exclude": []
11
+ }