@@ -499,7 +499,7 @@ type NodeAndTEAL = {
499
499
export default class Compiler {
500
500
static diagsRan : string [ ] = [ '' ] ;
501
501
502
- private scratch : { [ name : string ] : { slot : number ; type : TypeInfo } } = { } ;
502
+ private scratch : { [ name : string ] : { slot ? : number ; type : TypeInfo } } = { } ;
503
503
504
504
private currentProgram : 'approval' | 'clear' | 'lsig' = 'approval' ;
505
505
@@ -5415,6 +5415,13 @@ export default class Compiler {
5415
5415
throw Error ( 'Scratch slot must be between 0 and 200 (inclusive). 201-256 is reserved for the compiler' ) ;
5416
5416
5417
5417
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 } ;
5418
5425
} else if ( init . isKind ( ts . SyntaxKind . CallExpression ) && init . getExpression ( ) . getText ( ) === 'TemplateVar' ) {
5419
5426
if ( init . getTypeArguments ( ) ?. length !== 1 ) throw Error ( 'TemplateVar must have one type argument ' ) ;
5420
5427
@@ -5610,21 +5617,46 @@ export default class Compiler {
5610
5617
5611
5618
// If this is a scratch slot
5612
5619
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 {
5614
5637
throw Error ( `Invalid scratch expression ${ chain [ 1 ] . getText ( ) } ` ) ;
5615
- if ( chain [ 1 ] . getNameNode ( ) . getText ( ) !== 'value' ) throw Error ( `Invalid scratch expression ${ chain [ 1 ] . getText ( ) } ` ) ;
5638
+ }
5616
5639
5617
- const name = chain [ 0 ] . getNameNode ( ) . getText ( ) ;
5640
+ let opcode : string ;
5618
5641
5619
5642
if ( newValue !== undefined ) {
5620
- this . processNewValue ( newValue ) ;
5643
+ this . processNode ( newValue ) ;
5621
5644
typeComparison ( this . lastType , this . scratch [ name ] . type ) ;
5622
- this . push ( chain [ 1 ] , `store ${ this . scratch [ name ] . slot } ` , this . scratch [ name ] . type ) ;
5645
+ opcode = 'store' ;
5623
5646
} else {
5624
- this . push ( chain [ 1 ] , `load ${ this . scratch [ name ] . slot } ` , this . scratch [ name ] . type ) ;
5647
+ opcode = 'load' ;
5625
5648
}
5626
5649
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
+
5628
5660
return ;
5629
5661
}
5630
5662
0 commit comments