31
ReactiveValue,
32
SourceLocation,
33
SpreadPattern,
34
+ ValidIdentifierName,
35
getHookKind,
36
+ makeIdentifierName,
37
} from "../HIR/HIR";
38
import { printPlace } from "../HIR/PrintHIR";
39
import { eachPatternOperand } from "../HIR/visitors";
70
71
export function codegenFunction(
72
fn: ReactiveFunction,
73
+ uniqueIdentifiers: Set<ValidIdentifierName>,
74
filename: string | null
75
): Result<CodegenFunction, CompilerError> {
73
- const cx = new Context(fn.env, fn.id ?? "[[ anonymous ]]", null);
76
+ const cx = new Context(
77
+ fn.env,
78
+ fn.id ?? "[[ anonymous ]]",
79
+ uniqueIdentifiers,
80
+ null
81
+ );
82
const compileResult = codegenReactiveFunction(cx, fn);
83
if (compileResult.isErr()) {
84
return compileResult;
103
compiled.body.body.unshift(
104
t.variableDeclaration("const", [
105
t.variableDeclarator(
98
- t.identifier("$"),
106
+ t.identifier(cx.synthesizeName("$")),
107
t.callExpression(t.identifier("useMemoCache"), [
108
t.numericLiteral(cacheCount),
109
])
223
temp: Temporaries;
224
errors: CompilerError = new CompilerError();
225
objectMethods: Map<IdentifierId, ObjectMethod> = new Map();
226
+ uniqueIdentifiers: Set<ValidIdentifierName>;
227
+ synthesizedNames: Map<string, ValidIdentifierName> = new Map();
228
229
constructor(
230
env: Environment,
231
fnName: string,
232
+ uniqueIdentifiers: Set<ValidIdentifierName>,
233
temporaries: Temporaries | null = null
234
) {
235
this.env = env;
236
this.fnName = fnName;
237
+ this.uniqueIdentifiers = uniqueIdentifiers;
238
this.temp = temporaries !== null ? new Map(temporaries) : new Map();
239
}
240
get nextCacheIndex(): number {
248
hasDeclared(identifier: Identifier): boolean {
249
return this.#declarations.has(identifier.id);
250
}
251
+
252
+ synthesizeName(name: string): ValidIdentifierName {
253
+ const previous = this.synthesizedNames.get(name);
254
+ if (previous !== undefined) {
255
+ return previous;
256
+ }
257
+ let validated = makeIdentifierName(name).value;
258
+ let index = 0;
259
+ while (this.uniqueIdentifiers.has(validated)) {
260
+ validated = makeIdentifierName(`${name}${index++}`).value;
261
+ }
262
+ this.uniqueIdentifiers.add(validated);
263
+ this.synthesizedNames.set(name, validated);
264
+ return validated;
265
+ }
266
}
267
268
function codegenBlock(cx: Context, block: ReactiveBlock): t.BlockStatement {
375
changeExpressionComments.push(printDependencyComment(dep));
376
const comparison = t.binaryExpression(
377
"!==",
351
- t.memberExpression(t.identifier("$"), t.numericLiteral(index), true),
378
+ t.memberExpression(
379
+ t.identifier(cx.synthesizeName("$")),
380
+ t.numericLiteral(index),
381
+ true
382
+ ),
383
depValue
384
);
385
386
if (cx.env.config.enableChangeVariableCodegen) {
356
- const changeIdentifier = t.identifier(`c_${index}`);
387
+ const changeIdentifier = t.identifier(cx.synthesizeName(`c_${index}`));
388
statements.push(
389
t.variableDeclaration("const", [
390
t.variableDeclarator(changeIdentifier, comparison),
398
t.expressionStatement(
399
t.assignmentExpression(
400
"=",
370
- t.memberExpression(t.identifier("$"), t.numericLiteral(index), true),
401
+ t.memberExpression(
402
+ t.identifier(cx.synthesizeName("$")),
403
+ t.numericLiteral(index),
404
+ true
405
+ ),
406
depValue
407
)
408
)
433
t.expressionStatement(
434
t.assignmentExpression(
435
"=",
401
- t.memberExpression(t.identifier("$"), t.numericLiteral(index), true),
436
+ t.memberExpression(
437
+ t.identifier(cx.synthesizeName("$")),
438
+ t.numericLiteral(index),
439
+ true
440
+ ),
441
wrapCacheDep(cx, name)
442
)
443
)
447
t.assignmentExpression(
448
"=",
449
name,
411
- t.memberExpression(t.identifier("$"), t.numericLiteral(index), true)
450
+ t.memberExpression(
451
+ t.identifier(cx.synthesizeName("$")),
452
+ t.numericLiteral(index),
453
+ true
454
+ )
455
)
456
)
457
);
469
t.expressionStatement(
470
t.assignmentExpression(
471
"=",
429
- t.memberExpression(t.identifier("$"), t.numericLiteral(index), true),
472
+ t.memberExpression(
473
+ t.identifier(cx.synthesizeName("$")),
474
+ t.numericLiteral(index),
475
+ true
476
+ ),
477
wrapCacheDep(cx, name)
478
)
479
)
483
t.assignmentExpression(
484
"=",
485
name,
439
- t.memberExpression(t.identifier("$"), t.numericLiteral(index), true)
486
+ t.memberExpression(
487
+ t.identifier(cx.synthesizeName("$")),
488
+ t.numericLiteral(index),
489
+ true
490
+ )
491
)
492
)
493
);
511
testCondition = t.binaryExpression(
512
"===",
513
t.memberExpression(
463
- t.identifier("$"),
514
+ t.identifier(cx.synthesizeName("$")),
515
t.numericLiteral(firstOutputIndex),
516
true
517
),
1392
new Context(
1393
cx.env,
1394
reactiveFunction.id ?? "[[ anonymous ]]",
1395
+ cx.uniqueIdentifiers,
1396
cx.temp
1397
),
1398
reactiveFunction
1595
pruneUnusedLValues(reactiveFunction);
1596
pruneHoistedContexts(reactiveFunction);
1597
const fn = codegenReactiveFunction(
1546
- new Context(cx.env, reactiveFunction.id ?? "[[ anonymous ]]", cx.temp),
1598
+ new Context(
1599
+ cx.env,
1600
+ reactiveFunction.id ?? "[[ anonymous ]]",
1601
+ cx.uniqueIdentifiers,
1602
+ cx.temp
1603
+ ),
1604
reactiveFunction
1605
).unwrap();
1606
if (instrValue.expr.type === "ArrowFunctionExpression") {