Skip to content

Commit 9dc1de8

Browse files
committed
feat: dynamic scratch slot
1 parent 0fc99a4 commit 9dc1de8

File tree

7 files changed

+250
-163
lines changed

7 files changed

+250
-163
lines changed

src/lib/compiler.ts

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ type NodeAndTEAL = {
499499
export default class Compiler {
500500
static diagsRan: string[] = [''];
501501

502-
private scratch: { [name: string]: { slot: number; type: TypeInfo } } = {};
502+
private scratch: { [name: string]: { slot?: number; type: TypeInfo } } = {};
503503

504504
private currentProgram: 'approval' | 'clear' | 'lsig' = 'approval';
505505

@@ -5415,6 +5415,13 @@ export default class Compiler {
54155415
throw Error('Scratch slot must be between 0 and 200 (inclusive). 201-256 is reserved for the compiler');
54165416

54175417
this.scratch[name] = { type, slot };
5418+
} else if (init.isKind(ts.SyntaxKind.CallExpression) && init.getExpression().getText() === 'DynamicScratchSlot') {
5419+
if (init.getTypeArguments()?.length !== 1) throw Error('ScratchSlot must have one type argument ');
5420+
5421+
const type = this.getTypeInfo(init.getTypeArguments()[0].getType());
5422+
const name = node.getNameNode().getText();
5423+
5424+
this.scratch[name] = { type };
54185425
} else if (init.isKind(ts.SyntaxKind.CallExpression) && init.getExpression().getText() === 'TemplateVar') {
54195426
if (init.getTypeArguments()?.length !== 1) throw Error('TemplateVar must have one type argument ');
54205427

@@ -5610,21 +5617,45 @@ export default class Compiler {
56105617

56115618
// If this is a scratch slot
56125619
if (chain[0].isKind(ts.SyntaxKind.PropertyAccessExpression) && this.scratch[chain[0].getNameNode().getText()]) {
5613-
if (!chain[1].isKind(ts.SyntaxKind.PropertyAccessExpression))
5620+
const name = chain[0].getNameNode().getText();
5621+
5622+
let slot: number | undefined;
5623+
5624+
// If this is a dynamic scratch slot
5625+
if (
5626+
chain[1].isKind(ts.SyntaxKind.CallExpression) &&
5627+
chain[2].isKind(ts.SyntaxKind.PropertyAccessExpression) &&
5628+
chain[2].getName() === 'value'
5629+
) {
5630+
this.processNode(chain[1].getArguments()[0]);
5631+
}
5632+
// else if this is a static scratch slot
5633+
else if (chain[1].isKind(ts.SyntaxKind.PropertyAccessExpression) && chain[1].getName() === 'value') {
5634+
slot = this.scratch[name].slot;
5635+
} else {
56145636
throw Error(`Invalid scratch expression ${chain[1].getText()}`);
5615-
if (chain[1].getNameNode().getText() !== 'value') throw Error(`Invalid scratch expression ${chain[1].getText()}`);
5637+
}
56165638

5617-
const name = chain[0].getNameNode().getText();
5639+
let opcode: string;
56185640

56195641
if (newValue !== undefined) {
5620-
this.processNewValue(newValue);
5642+
this.processNode(newValue);
56215643
typeComparison(this.lastType, this.scratch[name].type);
5622-
this.push(chain[1], `store ${this.scratch[name].slot}`, this.scratch[name].type);
5644+
opcode = 'store';
56235645
} else {
5624-
this.push(chain[1], `load ${this.scratch[name].slot}`, this.scratch[name].type);
5646+
opcode = 'load';
56255647
}
56265648

5627-
chain.splice(0, 2);
5649+
if (slot !== undefined) {
5650+
opcode += ` ${slot}`;
5651+
} else {
5652+
opcode += 's';
5653+
}
5654+
5655+
this.push(chain[1], opcode, this.scratch[name].type);
5656+
5657+
chain.splice(0, slot === undefined ? 3 : 2);
5658+
56285659
return;
56295660
}
56305661

0 commit comments

Comments
 (0)