Skip to content

Commit 0734311

Browse files
authored
Merge pull request #442 from algorandfoundation/feat/dynamic_scratch_slot
feat: dynamic scratch slot
2 parents 0fc99a4 + df5b212 commit 0734311

File tree

7 files changed

+251
-163
lines changed

7 files changed

+251
-163
lines changed

src/lib/compiler.ts

Lines changed: 40 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,46 @@ 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+
typeComparison(this.lastType, StackType.uint64);
5632+
}
5633+
// else if this is a static scratch slot
5634+
else if (chain[1].isKind(ts.SyntaxKind.PropertyAccessExpression) && chain[1].getName() === 'value') {
5635+
slot = this.scratch[name].slot;
5636+
} else {
56145637
throw Error(`Invalid scratch expression ${chain[1].getText()}`);
5615-
if (chain[1].getNameNode().getText() !== 'value') throw Error(`Invalid scratch expression ${chain[1].getText()}`);
5638+
}
56165639

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

56195642
if (newValue !== undefined) {
5620-
this.processNewValue(newValue);
5643+
this.processNode(newValue);
56215644
typeComparison(this.lastType, this.scratch[name].type);
5622-
this.push(chain[1], `store ${this.scratch[name].slot}`, this.scratch[name].type);
5645+
opcode = 'store';
56235646
} else {
5624-
this.push(chain[1], `load ${this.scratch[name].slot}`, this.scratch[name].type);
5647+
opcode = 'load';
56255648
}
56265649

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

0 commit comments

Comments
 (0)