@@ -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,45 @@ 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
+ }
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 {
5614
5636
throw Error ( `Invalid scratch expression ${ chain [ 1 ] . getText ( ) } ` ) ;
5615
- if ( chain [ 1 ] . getNameNode ( ) . getText ( ) !== 'value' ) throw Error ( `Invalid scratch expression ${ chain [ 1 ] . getText ( ) } ` ) ;
5637
+ }
5616
5638
5617
- const name = chain [ 0 ] . getNameNode ( ) . getText ( ) ;
5639
+ let opcode : string ;
5618
5640
5619
5641
if ( newValue !== undefined ) {
5620
- this . processNewValue ( newValue ) ;
5642
+ this . processNode ( newValue ) ;
5621
5643
typeComparison ( this . lastType , this . scratch [ name ] . type ) ;
5622
- this . push ( chain [ 1 ] , `store ${ this . scratch [ name ] . slot } ` , this . scratch [ name ] . type ) ;
5644
+ opcode = 'store' ;
5623
5645
} else {
5624
- this . push ( chain [ 1 ] , `load ${ this . scratch [ name ] . slot } ` , this . scratch [ name ] . type ) ;
5646
+ opcode = 'load' ;
5625
5647
}
5626
5648
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
+
5628
5659
return ;
5629
5660
}
5630
5661
0 commit comments