Skip to content

Commit 7f4e9a4

Browse files
committed
Implement encoding/decoding of original scope variables
1 parent 2916385 commit 7f4e9a4

File tree

4 files changed

+57
-0
lines changed

4 files changed

+57
-0
lines changed

src/codec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export type Item =
3737
| typeof EmptyItem
3838
| OriginalScopeStartItem
3939
| OriginalScopeEndItem
40+
| OriginalScopeVariablesItem
4041
| GeneratedRangeStartItem
4142
| GeneratedRangeEndItem;
4243

@@ -55,6 +56,11 @@ interface OriginalScopeEndItem {
5556
column: number;
5657
}
5758

59+
interface OriginalScopeVariablesItem {
60+
tag: Tag.ORIGINAL_SCOPE_VARIABLES;
61+
variableIdxs: number[];
62+
}
63+
5864
interface GeneratedRangeStartItem {
5965
tag: Tag.GENERATED_RANGE_START;
6066
flags: number;

src/decode/decode.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const DEFAULT_SCOPE_STATE = {
2828
line: 0,
2929
name: 0,
3030
kind: 0,
31+
variable: 0,
3132
};
3233

3334
const DEFAULT_RANGE_STATE = {
@@ -95,6 +96,22 @@ class Decoder {
9596
this.#countToScope.set(this.#scopeCounter++, scope);
9697
break;
9798
}
99+
case Tag.ORIGINAL_SCOPE_VARIABLES: {
100+
const scope = this.#scopeStack.at(-1);
101+
if (!scope) {
102+
throw new Error(
103+
"Encountered ORIGINAL_SCOPE_VARIABLES without surrounding ORIGINAL_SCOPE_START",
104+
);
105+
}
106+
107+
for (const variableIdx of item.variableIdxs) {
108+
this.#scopeState.variable += variableIdx;
109+
scope.variables.push(this.#names[this.#scopeState.variable]);
110+
111+
// TODO: Potentially throw if we decode an illegal index.
112+
}
113+
break;
114+
}
98115
case Tag.ORIGINAL_SCOPE_END: {
99116
this.#scopeState.line += item.line;
100117

@@ -226,6 +243,16 @@ class Decoder {
226243
yield item;
227244
break;
228245
}
246+
case Tag.ORIGINAL_SCOPE_VARIABLES: {
247+
const variableIdxs: number[] = [];
248+
249+
while (iter.hasNext() && iter.peek() !== ",") {
250+
variableIdxs.push(iter.nextSignedVLQ());
251+
}
252+
253+
yield { tag, variableIdxs };
254+
break;
255+
}
229256
case Tag.ORIGINAL_SCOPE_END: {
230257
yield {
231258
tag,

src/encode/encoder.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const DEFAULT_SCOPE_STATE = {
1515
column: 0,
1616
name: 0,
1717
kind: 0,
18+
variable: 0,
1819
};
1920

2021
const DEFAULT_RANGE_STATE = {
@@ -64,6 +65,7 @@ export class Encoder {
6465
}
6566

6667
this.#encodeOriginalScopeStart(scope);
68+
this.#encodeOriginalScopeVariables(scope);
6769
scope.children.forEach((child) => this.#encodeOriginalScope(child));
6870
this.#encodeOriginalScopeEnd(scope);
6971
}
@@ -104,6 +106,20 @@ export class Encoder {
104106
this.#scopeToCount.set(scope, this.#scopeCounter++);
105107
}
106108

109+
#encodeOriginalScopeVariables(scope: OriginalScope) {
110+
if (scope.variables.length === 0) return;
111+
112+
this.#encodeTag(EncodedTag.ORIGINAL_SCOPE_VARIABLES);
113+
114+
for (const variable of scope.variables) {
115+
const idx = this.#resolveNamesIdx(variable);
116+
this.#encodeSigned(idx - this.#scopeState.variable);
117+
this.#scopeState.variable = idx;
118+
}
119+
120+
this.#finishItem();
121+
}
122+
107123
#encodeOriginalScopeEnd(scope: OriginalScope) {
108124
const { line, column } = scope.end;
109125
this.#verifyPositionWithScopeState(line, column);

src/roundtrip.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,12 @@ describe("round trip", () => {
132132

133133
assertCodec(builder.build());
134134
});
135+
136+
it("handles OriginalScope variables", () => {
137+
builder.startScope(0, 0, { variables: ["foo", "bar"] }).startScope(10, 0, {
138+
variables: ["local1", "local2"],
139+
}).endScope(20, 0).endScope(30, 0);
140+
141+
assertCodec(builder.build());
142+
});
135143
});

0 commit comments

Comments
 (0)