Skip to content

Commit 8c00726

Browse files
authored
Merge pull request #158 from ethdebug/rename-pointer-template-variables
Add template yields and inline template definitions
2 parents 478aaad + 4e9d0ac commit 8c00726

15 files changed

Lines changed: 671 additions & 36 deletions

File tree

packages/format/src/types/pointer/pointer.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,15 +130,17 @@ export namespace Pointer {
130130
| Collection.List
131131
| Collection.Conditional
132132
| Collection.Scope
133-
| Collection.Reference;
133+
| Collection.Reference
134+
| Collection.Templates;
134135

135136
export const isCollection = (value: unknown): value is Collection =>
136137
[
137138
Collection.isGroup,
138139
Collection.isList,
139140
Collection.isConditional,
140141
Collection.isScope,
141-
Collection.isReference
142+
Collection.isReference,
143+
Collection.isTemplates
142144
].some(guard => guard(value));
143145

144146
export namespace Collection {
@@ -208,13 +210,38 @@ export namespace Pointer {
208210

209211
export interface Reference {
210212
template: string;
213+
yields?: Record<string, string>;
211214
}
212215

213216
export const isReference = (value: unknown): value is Reference =>
214217
!!value &&
215218
typeof value === "object" &&
216219
"template" in value &&
217-
typeof value.template === "string" && !!value.template
220+
typeof value.template === "string" && !!value.template &&
221+
(!("yields" in value) || (
222+
typeof value.yields === "object" &&
223+
value.yields !== null &&
224+
Object.entries(value.yields as Record<string, unknown>).every(
225+
([k, v]) => isIdentifier(k) && isIdentifier(v)
226+
)
227+
))
228+
229+
export interface Templates {
230+
templates: {
231+
[identifier: string]: Pointer.Template;
232+
};
233+
in: Pointer;
234+
}
235+
236+
export const isTemplates = (value: unknown): value is Templates =>
237+
!!value &&
238+
typeof value === "object" &&
239+
"templates" in value &&
240+
typeof value.templates === "object" && !!value.templates &&
241+
Object.keys(value.templates).every(isIdentifier) &&
242+
Object.values(value.templates).every(isTemplate) &&
243+
"in" in value &&
244+
isPointer(value.in);
218245
}
219246

220247
export type Expression =

packages/pointers/src/dereference/generate.ts

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,85 @@ export async function* generateRegions(
3535
variables
3636
} = options;
3737

38+
// Stack of rename mappings for template references with yields
39+
const renameStack: Array<Record<string, string>> = [];
40+
41+
// Stack of template definitions for inline templates
42+
const templatesStack: Array<Pointer.Templates> = [];
43+
3844
const stack: Memo[] = [Memo.dereferencePointer(pointer)];
3945
while (stack.length > 0) {
4046
const memo: Memo = stack.pop() as Memo;
4147

4248
let memos: Memo[] = [];
4349
switch (memo.kind) {
4450
case "dereference-pointer": {
45-
memos = yield* processPointer(memo.pointer, options);
51+
// Merge inline templates with base templates (inline takes precedence)
52+
const currentTemplates = templatesStack.reduce(
53+
(acc, templates) => ({ ...acc, ...templates }),
54+
options.templates
55+
);
56+
57+
// Process the pointer, intercepting yielded regions to apply renames
58+
const process = processPointer(memo.pointer, {
59+
...options,
60+
templates: currentTemplates
61+
});
62+
let result = await process.next();
63+
while (!result.done) {
64+
let region = result.value;
65+
66+
// Apply rename if in context and region has a name in mapping
67+
const currentMapping = renameStack[renameStack.length - 1];
68+
if (currentMapping && region.name) {
69+
const newName = currentMapping[region.name];
70+
if (newName && newName !== region.name) {
71+
region = { ...region, name: newName };
72+
}
73+
}
74+
75+
yield region;
76+
result = await process.next();
77+
}
78+
memos = result.value;
4679
break;
4780
}
4881
case "save-regions": {
49-
Object.assign(regions, memo.regions);
82+
for (const [name, region] of Object.entries(memo.regions)) {
83+
// Save under original name for internal reference resolution
84+
regions[name] = region;
85+
}
5086
break;
5187
}
5288
case "save-variables": {
5389
Object.assign(variables, memo.variables);
5490
break;
5591
}
92+
case "push-region-renames": {
93+
renameStack.push(memo.mapping);
94+
break;
95+
}
96+
case "pop-region-renames": {
97+
// Apply renames when exiting the context: add mappings from
98+
// original names to new names for external reference resolution
99+
const mapping = renameStack.pop();
100+
if (mapping) {
101+
for (const [originalName, newName] of Object.entries(mapping)) {
102+
if (originalName in regions && newName !== originalName) {
103+
regions[newName] = { ...regions[originalName], name: newName };
104+
}
105+
}
106+
}
107+
break;
108+
}
109+
case "push-templates": {
110+
templatesStack.push(memo.templates);
111+
break;
112+
}
113+
case "pop-templates": {
114+
templatesStack.pop();
115+
break;
116+
}
56117
}
57118

58119
// add new memos to the stack in reverse order

0 commit comments

Comments
 (0)