Skip to content

Commit 9b64e5a

Browse files
authored
Merge pull request #443 from algorandfoundation/feat/dynamic_scratch_slot
fix: increment scratch slots
2 parents 0734311 + 9e74aa5 commit 9b64e5a

File tree

6 files changed

+141
-3
lines changed

6 files changed

+141
-3
lines changed

src/lib/compiler.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3580,6 +3580,23 @@ export default class Compiler {
35803580
storageName = getStorageName(node.getExpression() as ts.PropertyAccessExpression);
35813581
} else storageName = getStorageName(node);
35823582

3583+
if (this.scratch[storageName!]) {
3584+
const scratch = this.scratch[storageName!];
3585+
const { slot, type } = scratch;
3586+
3587+
typeComparison(this.lastType, type);
3588+
if (slot !== undefined) {
3589+
this.pushVoid(node, `store ${slot}`);
3590+
} else {
3591+
const call = node.getDescendantsOfKind(ts.SyntaxKind.CallExpression)[0];
3592+
3593+
this.processNode(call.getArguments()[0]);
3594+
this.pushVoid(node, 'swap');
3595+
this.pushVoid(node, `stores`);
3596+
}
3597+
3598+
return;
3599+
}
35833600
const storageProp = this.storageProps[storageName!];
35843601

35853602
const { type, valueType } = storageProp;
@@ -4545,7 +4562,7 @@ export default class Compiler {
45454562
.getFirstChild()
45464563
?.getType()
45474564
.getText()
4548-
.match(/(Box|LocalState|GlobalState)Value/);
4565+
.match(/(Scratch|Box|LocalState|GlobalState)Value/);
45494566

45504567
const isExprChain =
45514568
leftNode.isKind(ts.SyntaxKind.ElementAccessExpression) ||

tests/contracts/artifacts/GeneralTest.approval.teal

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2238,6 +2238,73 @@ dynamicScratchSlot:
22382238
assert
22392239
retsub
22402240

2241+
// incrementScratchSlot()void
2242+
*abi_route_incrementScratchSlot:
2243+
// execute incrementScratchSlot()void
2244+
callsub incrementScratchSlot
2245+
int 1
2246+
return
2247+
2248+
// incrementScratchSlot(): void
2249+
incrementScratchSlot:
2250+
proto 0 0
2251+
2252+
// tests/contracts/general.algo.ts:448
2253+
// this.scratch.value = 1337
2254+
int 1337
2255+
store 0
2256+
2257+
// tests/contracts/general.algo.ts:449
2258+
// this.scratch.value += 1
2259+
load 0
2260+
int 1
2261+
+
2262+
store 0
2263+
2264+
// tests/contracts/general.algo.ts:450
2265+
// assert(this.scratch.value === 1338)
2266+
load 0
2267+
int 1338
2268+
==
2269+
assert
2270+
retsub
2271+
2272+
// incrementDynamicScratchSlot()void
2273+
*abi_route_incrementDynamicScratchSlot:
2274+
// execute incrementDynamicScratchSlot()void
2275+
callsub incrementDynamicScratchSlot
2276+
int 1
2277+
return
2278+
2279+
// incrementDynamicScratchSlot(): void
2280+
incrementDynamicScratchSlot:
2281+
proto 0 0
2282+
2283+
// tests/contracts/general.algo.ts:454
2284+
// this.dynamicScratch(2).value = 1337
2285+
int 2
2286+
int 1337
2287+
stores
2288+
2289+
// tests/contracts/general.algo.ts:455
2290+
// this.dynamicScratch(2).value += 1
2291+
int 2
2292+
loads
2293+
int 1
2294+
+
2295+
int 2
2296+
swap
2297+
stores
2298+
2299+
// tests/contracts/general.algo.ts:456
2300+
// assert(this.dynamicScratch(2).value === 1338)
2301+
int 2
2302+
loads
2303+
int 1338
2304+
==
2305+
assert
2306+
retsub
2307+
22412308
*abi_route_createApplication:
22422309
int 1
22432310
return
@@ -2309,8 +2376,10 @@ dynamicScratchSlot:
23092376
method "staticValueLen(uint256)void"
23102377
method "staticTypeLen()void"
23112378
method "dynamicScratchSlot()void"
2379+
method "incrementScratchSlot()void"
2380+
method "incrementDynamicScratchSlot()void"
23122381
txna ApplicationArgs 0
2313-
match *abi_route_txnTypeEnum *abi_route_txnGroupLength *abi_route_asserts *abi_route_verifyTxnFromArg *abi_route_verifyTxnFromTxnGroup *abi_route_verifyTxnCondition *abi_route_verifyTxnIncludedIn *abi_route_verifyTxnNotIncludedIn *abi_route_submitPendingGroup *abi_route_methodWithTxnArgs *abi_route_shift *abi_route_fromBytes *abi_route_fromUint64 *abi_route_bzeroFunction *abi_route_events *abi_route_letOptimization *abi_route_staticContractProperties *abi_route_numberToString *abi_route_methodOnParens *abi_route_stringSubstring *abi_route_idProperty *abi_route_scratchSlot *abi_route_ecdsa *abi_route_verifyTxnTypes *abi_route_stringPlusEquals *abi_route_importedProgram *abi_route_callPrivateDefinedLater *abi_route_interalPublicMethod *abi_route_callInternalPublicMethod *abi_route_appLoadScratch *abi_route_uintNWithUnderscore *abi_route_opUp *abi_route_returnValueOnAssignment *abi_route_returnArrayValueOnAssignment *abi_route_returnStorageValueOnAssignment *abi_route_returnOperatorAssignmentValue *abi_route_returnArrayValueOnOperatorAssignment *abi_route_returnArrayInStorageValueOnOperatorAssignment *abi_route_consts *abi_route_assertWithMessage *abi_route_opcodeAliases *abi_route_vrfVerifyOp *abi_route_ecMath *abi_route_gitxn *abi_route_getSetBytes *abi_route_getSetUint64 *abi_route_blockOp *abi_route_b64 *abi_route_json *abi_route_bitlenOp *abi_route_computedConst *abi_route_multiComputedConst *abi_route_computedConstAsStaticArrayLength *abi_route_readSchema *abi_route_comparisonOr *abi_route_txnArgsMethod *abi_route_callTxnArgsMethod *abi_route_staticValueLen *abi_route_staticTypeLen *abi_route_dynamicScratchSlot
2382+
match *abi_route_txnTypeEnum *abi_route_txnGroupLength *abi_route_asserts *abi_route_verifyTxnFromArg *abi_route_verifyTxnFromTxnGroup *abi_route_verifyTxnCondition *abi_route_verifyTxnIncludedIn *abi_route_verifyTxnNotIncludedIn *abi_route_submitPendingGroup *abi_route_methodWithTxnArgs *abi_route_shift *abi_route_fromBytes *abi_route_fromUint64 *abi_route_bzeroFunction *abi_route_events *abi_route_letOptimization *abi_route_staticContractProperties *abi_route_numberToString *abi_route_methodOnParens *abi_route_stringSubstring *abi_route_idProperty *abi_route_scratchSlot *abi_route_ecdsa *abi_route_verifyTxnTypes *abi_route_stringPlusEquals *abi_route_importedProgram *abi_route_callPrivateDefinedLater *abi_route_interalPublicMethod *abi_route_callInternalPublicMethod *abi_route_appLoadScratch *abi_route_uintNWithUnderscore *abi_route_opUp *abi_route_returnValueOnAssignment *abi_route_returnArrayValueOnAssignment *abi_route_returnStorageValueOnAssignment *abi_route_returnOperatorAssignmentValue *abi_route_returnArrayValueOnOperatorAssignment *abi_route_returnArrayInStorageValueOnOperatorAssignment *abi_route_consts *abi_route_assertWithMessage *abi_route_opcodeAliases *abi_route_vrfVerifyOp *abi_route_ecMath *abi_route_gitxn *abi_route_getSetBytes *abi_route_getSetUint64 *abi_route_blockOp *abi_route_b64 *abi_route_json *abi_route_bitlenOp *abi_route_computedConst *abi_route_multiComputedConst *abi_route_computedConstAsStaticArrayLength *abi_route_readSchema *abi_route_comparisonOr *abi_route_txnArgsMethod *abi_route_callTxnArgsMethod *abi_route_staticValueLen *abi_route_staticTypeLen *abi_route_dynamicScratchSlot *abi_route_incrementScratchSlot *abi_route_incrementDynamicScratchSlot
23142383
err
23152384

23162385
*intToAscii:

tests/contracts/artifacts/GeneralTest.arc32.json

Lines changed: 25 additions & 1 deletion
Large diffs are not rendered by default.

tests/contracts/artifacts/GeneralTest.arc4.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,20 @@
478478
"type": "void"
479479
}
480480
},
481+
{
482+
"name": "incrementScratchSlot",
483+
"args": [],
484+
"returns": {
485+
"type": "void"
486+
}
487+
},
488+
{
489+
"name": "incrementDynamicScratchSlot",
490+
"args": [],
491+
"returns": {
492+
"type": "void"
493+
}
494+
},
481495
{
482496
"name": "createApplication",
483497
"args": [],

tests/contracts/general.algo.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,4 +443,16 @@ class GeneralTest extends Contract {
443443
this.dynamicScratch(1).value = 1337;
444444
assert(this.dynamicScratch(1).value === 1337);
445445
}
446+
447+
incrementScratchSlot(): void {
448+
this.scratch.value = 1337;
449+
this.scratch.value += 1;
450+
assert(this.scratch.value === 1338);
451+
}
452+
453+
incrementDynamicScratchSlot(): void {
454+
this.dynamicScratch(2).value = 1337;
455+
this.dynamicScratch(2).value += 1;
456+
assert(this.dynamicScratch(2).value === 1338);
457+
}
446458
}

tests/general.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ describe('General', function () {
3636
'callInternalPublicMethod',
3737
'opUp',
3838
'dynamicScratchSlot',
39+
'incrementScratchSlot',
40+
'incrementDynamicScratchSlot',
3941
].forEach((method) => {
4042
test(method, async function () {
4143
const { appClient } = await compileAndCreate(await sender, PATH, ARTIFACTS_DIR, NAME);

0 commit comments

Comments
 (0)