From e0a6fae04b4090ea694ce700a674b1969e0e0169 Mon Sep 17 00:00:00 2001 From: Tristan Menzel Date: Thu, 10 Oct 2024 10:07:05 -0700 Subject: [PATCH] feat: Implement missing box proxy methods --- src/awst_build/eb/storage/box.ts | 559 -------- src/awst_build/eb/storage/box/base.ts | 71 + src/awst_build/eb/storage/box/box-map.ts | 235 +++ src/awst_build/eb/storage/box/box-ref.ts | 215 +++ src/awst_build/eb/storage/box/box.ts | 163 +++ src/awst_build/eb/storage/box/index.ts | 4 + src/awst_build/type-resolver.ts | 2 +- tests/approvals/box-proxies.algo.ts | 13 +- tests/approvals/out/box-proxies.awst | 12 +- tests/approvals/out/box-proxies.awst.json | 1591 ++++++++++++++++----- 10 files changed, 1963 insertions(+), 902 deletions(-) delete mode 100644 src/awst_build/eb/storage/box.ts create mode 100644 src/awst_build/eb/storage/box/base.ts create mode 100644 src/awst_build/eb/storage/box/box-map.ts create mode 100644 src/awst_build/eb/storage/box/box-ref.ts create mode 100644 src/awst_build/eb/storage/box/box.ts create mode 100644 src/awst_build/eb/storage/box/index.ts diff --git a/src/awst_build/eb/storage/box.ts b/src/awst_build/eb/storage/box.ts deleted file mode 100644 index 88e8215d..00000000 --- a/src/awst_build/eb/storage/box.ts +++ /dev/null @@ -1,559 +0,0 @@ -import { intrinsicFactory } from '../../../awst/intrinsic-factory' -import { nodeFactory } from '../../../awst/node-factory' -import type { BoxValueExpression, Expression } from '../../../awst/nodes' -import { BytesConstant } from '../../../awst/nodes' -import type { SourceLocation } from '../../../awst/source-location' -import { boolWType, boxKeyWType, bytesWType, voidWType } from '../../../awst/wtypes' -import { codeInvariant, invariant } from '../../../util' -import { AppStorageDeclaration } from '../../contract-data' -import type { ContractClassPType, PType } from '../../ptypes' -import { - boolPType, - BoxMapPType, - BoxPType, - BoxRefPType, - boxRefType, - bytesPType, - stringPType, - TuplePType, - uint64PType, - voidPType, -} from '../../ptypes' -import { instanceEb, typeRegistry } from '../../type-registry' -import { BooleanExpressionBuilder } from '../boolean-expression-builder' -import type { InstanceBuilder, NodeBuilder } from '../index' -import { FunctionBuilder, InstanceExpressionBuilder, ParameterlessFunctionBuilder } from '../index' -import { requireExpressionOfType } from '../util' -import { parseFunctionArgs } from '../util/arg-parsing' -import { VoidExpressionBuilder } from '../void-expression-builder' -import { extractKey } from './util' -import { ValueProxy } from './value-proxy' - -export class BoxFunctionBuilder extends FunctionBuilder { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - ptypes: [contentPType], - args: [{ key }], - } = parseFunctionArgs({ - args, - typeArgs, - funcName: `Box`, - callLocation: sourceLocation, - genericTypeArgs: 1, - argSpec: (a) => [a.obj({ key: a.required(bytesPType, stringPType) })], - }) - - const ptype = new BoxPType({ content: contentPType }) - return new BoxExpressionBuilder(extractKey(key, boxKeyWType), ptype) - } -} -export class BoxRefFunctionBuilder extends FunctionBuilder { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - args: [{ key }], - } = parseFunctionArgs({ - args, - typeArgs, - funcName: `BoxRef`, - callLocation: sourceLocation, - genericTypeArgs: 0, - argSpec: (a) => [a.obj({ key: a.required(bytesPType, stringPType) })], - }) - - return new BoxRefExpressionBuilder(extractKey(key, boxKeyWType), boxRefType) - } -} -export class BoxMapFunctionBuilder extends FunctionBuilder { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - ptypes: [keySuffixType, contentPType], - args: [{ keyPrefix }], - } = parseFunctionArgs({ - args, - typeArgs, - funcName: `BoxMap`, - callLocation: sourceLocation, - genericTypeArgs: 2, - argSpec: (a) => [a.obj({ keyPrefix: a.required(bytesPType, stringPType) })], - }) - - const ptype = new BoxMapPType({ content: contentPType, keyType: keySuffixType }) - return new BoxMapExpressionBuilder(extractKey(keyPrefix, boxKeyWType), ptype) - } -} - -export abstract class BoxProxyExpressionBuilder< - TProxyType extends BoxMapPType | BoxRefPType | BoxPType, -> extends InstanceExpressionBuilder { - buildStorageDeclaration(memberName: string, memberLocation: SourceLocation, contractType: ContractClassPType): AppStorageDeclaration { - codeInvariant( - this._expr instanceof BytesConstant, - `key${this.ptype instanceof BoxMapPType ? ' prefix' : ''} must be a compile time constant value if ${this.typeDescription} is assigned to a contract member`, - ) - return new AppStorageDeclaration({ - sourceLocation: memberLocation, - ptype: this.ptype, - memberName: memberName, - keyOverride: this._expr ?? null, - description: null, - definedIn: contractType, - }) - } -} - -export class BoxMapExpressionBuilder extends BoxProxyExpressionBuilder { - constructor(expr: Expression, ptype: PType) { - invariant(ptype instanceof BoxMapPType, 'BoxMapExpressionBuilder must be constructed with ptype of BoxMapPType') - super(expr, ptype) - } - memberAccess(name: string, sourceLocation: SourceLocation): NodeBuilder { - switch (name) { - case 'set': - return new BoxMapSetFunctionBuilder(this._expr, this.ptype, sourceLocation) - case 'delete': - return new BoxMapDeleteFunctionBuilder(this._expr, this.ptype, sourceLocation) - case 'get': - return new BoxMapGetFunctionBuilder(this._expr, this.ptype, sourceLocation) - case 'has': - return new BoxMapHasFunctionBuilder(this._expr, this.ptype, sourceLocation) - } - return super.memberAccess(name, sourceLocation) - } -} -export class BoxRefExpressionBuilder extends BoxProxyExpressionBuilder { - constructor(expr: Expression, ptype: PType) { - invariant(ptype instanceof BoxRefPType, 'BoxRefExpressionBuilder must be constructed with ptype of BoxRefPType') - super(expr, ptype) - } - - memberAccess(name: string, sourceLocation: SourceLocation): NodeBuilder { - const boxValueExpr = boxValue({ - key: this._expr, - sourceLocation, - contentType: this.ptype.contentType, - }) - switch (name) { - case 'put': - return new BoxRefPutFunctionBuilder(boxValueExpr) - case 'splice': - return new BoxRefSpliceFunctionBuilder(boxValueExpr) - case 'create': - return new BoxRefCreateFunctionBuilder(boxValueExpr) - case 'extract': - return new BoxRefExtractFunctionBuilder(boxValueExpr) - case 'replace': - return new BoxRefReplaceFunctionBuilder(boxValueExpr) - case 'value': - return new BoxValueExpressionBuilder(boxValueExpr, this.ptype.contentType) - } - return super.memberAccess(name, sourceLocation) - } -} - -export abstract class BoxRefBaseFunctionBuilder extends FunctionBuilder { - constructor(protected readonly boxValue: BoxValueExpression) { - super(boxValue.sourceLocation) - } -} - -export class BoxRefCreateFunctionBuilder extends BoxRefBaseFunctionBuilder { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - args: [{ size }], - } = parseFunctionArgs({ - args, - typeArgs, - genericTypeArgs: 0, - funcName: 'BoxRef.create', - callLocation: sourceLocation, - argSpec: (a) => [a.obj({ size: a.required(uint64PType) })], - }) - return instanceEb( - nodeFactory.intrinsicCall({ - opCode: 'box_create', - stackArgs: [this.boxValue, size.resolve()], - wtype: boolWType, - immediates: [], - sourceLocation, - }), - boolPType, - ) - } -} -export class BoxRefExtractFunctionBuilder extends BoxRefBaseFunctionBuilder { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - args: [start, length], - } = parseFunctionArgs({ - args, - typeArgs, - genericTypeArgs: 0, - funcName: 'BoxRef.extract', - callLocation: sourceLocation, - argSpec: (a) => [a.required(uint64PType), a.required(uint64PType)], - }) - return instanceEb( - nodeFactory.intrinsicCall({ - opCode: 'box_extract', - stackArgs: [this.boxValue, start.resolve(), length.resolve()], - wtype: bytesWType, - immediates: [], - sourceLocation, - }), - bytesPType, - ) - } -} -export class BoxRefReplaceFunctionBuilder extends BoxRefBaseFunctionBuilder { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - args: [start, value], - } = parseFunctionArgs({ - args, - typeArgs, - genericTypeArgs: 0, - funcName: 'BoxRef.replace', - callLocation: sourceLocation, - argSpec: (a) => [a.required(uint64PType), a.required(bytesPType)], - }) - return instanceEb( - nodeFactory.intrinsicCall({ - opCode: 'box_replace', - stackArgs: [this.boxValue, start.resolve(), value.resolve()], - wtype: voidWType, - immediates: [], - sourceLocation, - }), - voidPType, - ) - } -} - -export class BoxRefPutFunctionBuilder extends BoxRefBaseFunctionBuilder { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - args: [value], - } = parseFunctionArgs({ - args, - typeArgs, - genericTypeArgs: 0, - funcName: 'BoxRef.put', - callLocation: sourceLocation, - argSpec: (a) => [a.required(bytesPType)], - }) - return instanceEb( - nodeFactory.intrinsicCall({ - opCode: 'box_put', - stackArgs: [this.boxValue, value.resolve()], - wtype: voidWType, - immediates: [], - sourceLocation, - }), - voidPType, - ) - } -} -export class BoxRefSpliceFunctionBuilder extends BoxRefBaseFunctionBuilder { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - args: [start, stop, value], - } = parseFunctionArgs({ - args, - typeArgs, - genericTypeArgs: 0, - funcName: 'BoxRef.splice', - callLocation: sourceLocation, - argSpec: (a) => [a.required(uint64PType), a.required(uint64PType), a.required(bytesPType)], - }) - return instanceEb( - nodeFactory.intrinsicCall({ - opCode: 'box_splice', - stackArgs: [this.boxValue, start.resolve(), stop.resolve(), value.resolve()], - wtype: voidWType, - immediates: [], - sourceLocation, - }), - voidPType, - ) - } -} - -function boxValue({ - key, - sourceLocation, - contentType, -}: { - key: Expression - sourceLocation: SourceLocation - contentType: PType -}): BoxValueExpression { - return nodeFactory.boxValueExpression({ - key, - sourceLocation, - wtype: contentType.wtypeOrThrow, - existsAssertionMessage: 'Box must have value', - }) -} - -export class BoxExpressionBuilder extends BoxProxyExpressionBuilder { - constructor(expr: Expression, ptype: PType) { - invariant(ptype instanceof BoxPType, 'BoxExpressionBuilder must be constructed with ptype of BoxPType') - super(expr, ptype) - } - - memberAccess(name: string, sourceLocation: SourceLocation): NodeBuilder { - const boxValueExpr = boxValue({ - key: this._expr, - sourceLocation, - contentType: this.ptype.contentType, - }) - switch (name) { - case 'value': - return new BoxValueExpressionBuilder(boxValueExpr, this.ptype.contentType) - case 'exists': - return new BooleanExpressionBuilder( - nodeFactory.stateExists({ - field: boxValueExpr, - sourceLocation, - wtype: boolWType, - }), - ) - case 'delete': - return new BoxDeleteFunctionBuilder(boxValueExpr, sourceLocation) - case 'get': - return new BoxGetFunctionBuilder(boxValueExpr, this.ptype.contentType, sourceLocation) - case 'maybe': - return new BoxMaybeFunctionBuilder(boxValueExpr, this.ptype.contentType, sourceLocation) - } - return super.memberAccess(name, sourceLocation) - } -} - -/** - * Wraps the box value expression and watches for certain expressions which can be optimized. - * - * For example box.value.bytes.slice(...) can be optimized to use box_extract directly rather - * than reading the entire box into memory and then slicing it. All unhandled scenarios are proxied - * through to the underlying builder for the given type. - */ -class BoxValueExpressionBuilder extends ValueProxy { - constructor(boxValue: BoxValueExpression, ptype: PType) { - super(boxValue, ptype) - } - assign(other: InstanceBuilder, sourceLocation: SourceLocation): InstanceBuilder { - const value = requireExpressionOfType(other, this.ptype) - return typeRegistry.getInstanceEb( - nodeFactory.assignmentExpression({ - target: this.resolveLValue(), - value, - sourceLocation, - }), - this.ptype, - ) - } -} -class BoxDeleteFunctionBuilder extends ParameterlessFunctionBuilder { - constructor(boxValue: BoxValueExpression, sourceLocation: SourceLocation) { - super( - boxValue, - (expr) => - new VoidExpressionBuilder( - nodeFactory.stateDelete({ - sourceLocation, - field: boxValue, - wtype: voidWType, - }), - ), - ) - } -} - -class BoxGetFunctionBuilder extends FunctionBuilder { - constructor( - private readonly boxValue: BoxValueExpression, - private readonly contentType: PType, - sourceLocation: SourceLocation, - ) { - super(sourceLocation) - } - - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - args: [{ default: defaultValue }], - } = parseFunctionArgs({ - args, - typeArgs, - funcName: 'Box.get', - callLocation: sourceLocation, - genericTypeArgs: 0, - argSpec: (a) => [a.obj({ default: a.optional(this.contentType) })], - }) - - if (defaultValue) { - return instanceEb( - nodeFactory.stateGet({ - sourceLocation, - default: defaultValue.resolve(), - wtype: this.contentType.wtypeOrThrow, - field: this.boxValue, - }), - this.contentType, - ) - } else { - return new BoxValueExpressionBuilder(this.boxValue, this.contentType) - } - } -} -class BoxMaybeFunctionBuilder extends FunctionBuilder { - constructor( - private readonly boxValue: BoxValueExpression, - private readonly contentType: PType, - sourceLocation: SourceLocation, - ) { - super(sourceLocation) - } - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - parseFunctionArgs({ - args, - typeArgs, - funcName: 'Box.maybe', - callLocation: sourceLocation, - genericTypeArgs: 0, - argSpec: () => [], - }) - const type = new TuplePType({ items: [this.contentType, boolPType], immutable: true }) - - return instanceEb( - nodeFactory.stateGetEx({ - sourceLocation, - wtype: type.wtype, - field: this.boxValue, - }), - type, - ) - } -} -abstract class BoxMapFunctionBuilderBase extends FunctionBuilder { - #mapPType: BoxMapPType - #boxMapExpr: Expression - constructor(boxMapExpr: Expression, mapPType: BoxMapPType, sourceLocation: SourceLocation) { - super(sourceLocation) - this.#mapPType = mapPType - this.#boxMapExpr = boxMapExpr - } - protected get contentType() { - return this.#mapPType.contentType - } - protected get keyType() { - return this.#mapPType.keyType - } - protected boxValueExpression(key: Expression): BoxValueExpression { - const keyBytes = instanceEb(key, this.keyType).toBytes(this.sourceLocation) - - return nodeFactory.boxValueExpression({ - sourceLocation: this.sourceLocation, - existsAssertionMessage: 'Box must have value', - key: intrinsicFactory.bytesConcat({ - left: this.#boxMapExpr, - right: keyBytes, - sourceLocation: this.sourceLocation, - }), - wtype: this.contentType.wtypeOrThrow, - }) - } -} -class BoxMapHasFunctionBuilder extends BoxMapFunctionBuilderBase { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - args: [key], - } = parseFunctionArgs({ - args, - typeArgs, - funcName: 'BoxMap.has', - callLocation: sourceLocation, - genericTypeArgs: 0, - argSpec: (a) => [a.required(this.keyType)], - }) - return new BooleanExpressionBuilder( - nodeFactory.stateExists({ - wtype: boolWType, - field: this.boxValueExpression(key.resolve()), - sourceLocation, - }), - ) - } -} - -class BoxMapGetFunctionBuilder extends BoxMapFunctionBuilderBase { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - args: [key, { default: defaultValue }], - } = parseFunctionArgs({ - args, - typeArgs, - funcName: 'BoxMap.set', - callLocation: sourceLocation, - genericTypeArgs: 0, - argSpec: (a) => [a.required(this.keyType), a.obj({ default: a.optional(this.contentType) })], - }) - - if (defaultValue) { - return instanceEb( - nodeFactory.stateGet({ - sourceLocation, - default: defaultValue.resolve(), - wtype: this.contentType.wtypeOrThrow, - field: this.boxValueExpression(key.resolve()), - }), - this.contentType, - ) - } else { - return new BoxValueExpressionBuilder(this.boxValueExpression(key.resolve()), this.contentType) - } - } -} -class BoxMapSetFunctionBuilder extends BoxMapFunctionBuilderBase { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - args: [key, value], - } = parseFunctionArgs({ - args, - typeArgs, - funcName: 'BoxMap.set', - callLocation: sourceLocation, - genericTypeArgs: 0, - argSpec: (a) => [a.required(this.keyType), a.required(this.contentType)], - }) - - return instanceEb( - nodeFactory.assignmentExpression({ - target: this.boxValueExpression(key.resolve()), - sourceLocation, - value: value.resolve(), - }), - this.contentType, - ) - } -} -class BoxMapDeleteFunctionBuilder extends BoxMapFunctionBuilderBase { - call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { - const { - args: [key], - } = parseFunctionArgs({ - args, - typeArgs, - funcName: 'BoxMap.delete', - callLocation: sourceLocation, - genericTypeArgs: 0, - argSpec: (a) => [a.required(this.keyType)], - }) - - return new VoidExpressionBuilder( - nodeFactory.stateDelete({ - field: this.boxValueExpression(key.resolve()), - sourceLocation, - wtype: voidWType, - }), - ) - } -} diff --git a/src/awst_build/eb/storage/box/base.ts b/src/awst_build/eb/storage/box/base.ts new file mode 100644 index 00000000..8041c4ce --- /dev/null +++ b/src/awst_build/eb/storage/box/base.ts @@ -0,0 +1,71 @@ +import { nodeFactory } from '../../../../awst/node-factory' +import { type BoxValueExpression, BytesConstant, type Expression } from '../../../../awst/nodes' +import type { SourceLocation } from '../../../../awst/source-location' +import { codeInvariant } from '../../../../util' +import { AppStorageDeclaration } from '../../../contract-data' +import type { BoxPType, BoxRefPType } from '../../../ptypes' +import { BoxMapPType, type ContractClassPType, type PType } from '../../../ptypes' +import { typeRegistry } from '../../../type-registry' +import { type InstanceBuilder, InstanceExpressionBuilder } from '../../index' +import { requireExpressionOfType } from '../../util' +import { ValueProxy } from '../value-proxy' + +export abstract class BoxProxyExpressionBuilder< + TProxyType extends BoxMapPType | BoxRefPType | BoxPType, +> extends InstanceExpressionBuilder { + buildStorageDeclaration(memberName: string, memberLocation: SourceLocation, contractType: ContractClassPType): AppStorageDeclaration { + codeInvariant( + this._expr instanceof BytesConstant, + `key${this.ptype instanceof BoxMapPType ? ' prefix' : ''} must be a compile time constant value if ${this.typeDescription} is assigned to a contract member`, + ) + return new AppStorageDeclaration({ + sourceLocation: memberLocation, + ptype: this.ptype, + memberName: memberName, + keyOverride: this._expr ?? null, + description: null, + definedIn: contractType, + }) + } +} + +/** + * Wraps the box value expression and watches for certain expressions which can be optimized. + * + * For example box.value.bytes.slice(...) can be optimized to use box_extract directly rather + * than reading the entire box into memory and then slicing it. All unhandled scenarios are proxied + * through to the underlying builder for the given type. + */ +export class BoxValueExpressionBuilder extends ValueProxy { + constructor(boxValue: BoxValueExpression, ptype: PType) { + super(boxValue, ptype) + } + assign(other: InstanceBuilder, sourceLocation: SourceLocation): InstanceBuilder { + const value = requireExpressionOfType(other, this.ptype) + return typeRegistry.getInstanceEb( + nodeFactory.assignmentExpression({ + target: this.resolveLValue(), + value, + sourceLocation, + }), + this.ptype, + ) + } +} + +export function boxValue({ + key, + sourceLocation, + contentType, +}: { + key: Expression + sourceLocation: SourceLocation + contentType: PType +}): BoxValueExpression { + return nodeFactory.boxValueExpression({ + key, + sourceLocation, + wtype: contentType.wtypeOrThrow, + existsAssertionMessage: 'Box must have value', + }) +} diff --git a/src/awst_build/eb/storage/box/box-map.ts b/src/awst_build/eb/storage/box/box-map.ts new file mode 100644 index 00000000..65dd5a31 --- /dev/null +++ b/src/awst_build/eb/storage/box/box-map.ts @@ -0,0 +1,235 @@ +import { intrinsicFactory } from '../../../../awst/intrinsic-factory' +import { nodeFactory } from '../../../../awst/node-factory' +import type { BoxValueExpression, Expression } from '../../../../awst/nodes' +import type { SourceLocation } from '../../../../awst/source-location' +import { boolWType, boxKeyWType, uint64WType, voidWType, WTuple } from '../../../../awst/wtypes' +import { invariant } from '../../../../util' +import type { PType } from '../../../ptypes' +import { boolPType, BoxMapPType, bytesPType, stringPType, TuplePType, uint64PType } from '../../../ptypes' +import { instanceEb } from '../../../type-registry' +import { BooleanExpressionBuilder } from '../../boolean-expression-builder' +import { FunctionBuilder, type InstanceBuilder, type NodeBuilder } from '../../index' +import { parseFunctionArgs } from '../../util/arg-parsing' +import { VoidExpressionBuilder } from '../../void-expression-builder' +import { extractKey } from '../util' +import { BoxProxyExpressionBuilder, BoxValueExpressionBuilder } from './base' + +export class BoxMapFunctionBuilder extends FunctionBuilder { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + ptypes: [keySuffixType, contentPType], + args: [{ keyPrefix }], + } = parseFunctionArgs({ + args, + typeArgs, + funcName: `BoxMap`, + callLocation: sourceLocation, + genericTypeArgs: 2, + argSpec: (a) => [a.obj({ keyPrefix: a.required(bytesPType, stringPType) })], + }) + + const ptype = new BoxMapPType({ content: contentPType, keyType: keySuffixType }) + return new BoxMapExpressionBuilder(extractKey(keyPrefix, boxKeyWType), ptype) + } +} + +export class BoxMapExpressionBuilder extends BoxProxyExpressionBuilder { + constructor(expr: Expression, ptype: PType) { + invariant(ptype instanceof BoxMapPType, 'BoxMapExpressionBuilder must be constructed with ptype of BoxMapPType') + super(expr, ptype) + } + memberAccess(name: string, sourceLocation: SourceLocation): NodeBuilder { + switch (name) { + case 'set': + return new BoxMapSetFunctionBuilder(this._expr, this.ptype, sourceLocation) + case 'delete': + return new BoxMapDeleteFunctionBuilder(this._expr, this.ptype, sourceLocation) + case 'get': + return new BoxMapGetFunctionBuilder(this._expr, this.ptype, sourceLocation) + case 'has': + return new BoxMapHasFunctionBuilder(this._expr, this.ptype, sourceLocation) + case 'maybe': + return new BoxMapMaybeFunctionBuilder(this._expr, this.ptype, sourceLocation) + case 'length': + return new BoxMapLengthFunctionBuilder(this._expr, this.ptype, sourceLocation) + } + return super.memberAccess(name, sourceLocation) + } +} + +abstract class BoxMapFunctionBuilderBase extends FunctionBuilder { + #mapPType: BoxMapPType + #boxMapExpr: Expression + constructor(boxMapExpr: Expression, mapPType: BoxMapPType, sourceLocation: SourceLocation) { + super(sourceLocation) + this.#mapPType = mapPType + this.#boxMapExpr = boxMapExpr + } + protected get contentType() { + return this.#mapPType.contentType + } + protected get keyType() { + return this.#mapPType.keyType + } + protected boxValueExpression(key: Expression): BoxValueExpression { + const keyBytes = instanceEb(key, this.keyType).toBytes(this.sourceLocation) + + return nodeFactory.boxValueExpression({ + sourceLocation: this.sourceLocation, + existsAssertionMessage: 'Box must have value', + key: intrinsicFactory.bytesConcat({ + left: this.#boxMapExpr, + right: keyBytes, + sourceLocation: this.sourceLocation, + }), + wtype: this.contentType.wtypeOrThrow, + }) + } +} +class BoxMapHasFunctionBuilder extends BoxMapFunctionBuilderBase { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [key], + } = parseFunctionArgs({ + args, + typeArgs, + funcName: 'BoxMap.has', + callLocation: sourceLocation, + genericTypeArgs: 0, + argSpec: (a) => [a.required(this.keyType)], + }) + return new BooleanExpressionBuilder( + nodeFactory.stateExists({ + wtype: boolWType, + field: this.boxValueExpression(key.resolve()), + sourceLocation, + }), + ) + } +} + +class BoxMapGetFunctionBuilder extends BoxMapFunctionBuilderBase { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [key, { default: defaultValue }], + } = parseFunctionArgs({ + args, + typeArgs, + funcName: 'BoxMap.get', + callLocation: sourceLocation, + genericTypeArgs: 0, + argSpec: (a) => [a.required(this.keyType), a.obj({ default: a.optional(this.contentType) })], + }) + + if (defaultValue) { + return instanceEb( + nodeFactory.stateGet({ + sourceLocation, + default: defaultValue.resolve(), + wtype: this.contentType.wtypeOrThrow, + field: this.boxValueExpression(key.resolve()), + }), + this.contentType, + ) + } else { + return new BoxValueExpressionBuilder(this.boxValueExpression(key.resolve()), this.contentType) + } + } +} +class BoxMapSetFunctionBuilder extends BoxMapFunctionBuilderBase { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [key, value], + } = parseFunctionArgs({ + args, + typeArgs, + funcName: 'BoxMap.set', + callLocation: sourceLocation, + genericTypeArgs: 0, + argSpec: (a) => [a.required(this.keyType), a.required(this.contentType)], + }) + + return instanceEb( + nodeFactory.assignmentExpression({ + target: this.boxValueExpression(key.resolve()), + sourceLocation, + value: value.resolve(), + }), + this.contentType, + ) + } +} +class BoxMapMaybeFunctionBuilder extends BoxMapFunctionBuilderBase { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [key], + } = parseFunctionArgs({ + args, + typeArgs, + funcName: 'BoxMap.maybe', + callLocation: sourceLocation, + genericTypeArgs: 0, + argSpec: (a) => [a.required(this.keyType)], + }) + const type = new TuplePType({ items: [this.contentType, boolPType], immutable: true }) + + return instanceEb( + nodeFactory.stateGetEx({ + field: this.boxValueExpression(key.resolve()), + sourceLocation, + wtype: type.wtype, + }), + type, + ) + } +} +class BoxMapLengthFunctionBuilder extends BoxMapFunctionBuilderBase { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [key], + } = parseFunctionArgs({ + args, + typeArgs, + funcName: 'BoxMap.length', + callLocation: sourceLocation, + genericTypeArgs: 0, + argSpec: (a) => [a.required(this.keyType)], + }) + + return instanceEb( + nodeFactory.checkedMaybe({ + expr: nodeFactory.intrinsicCall({ + opCode: 'box_length', + stackArgs: [this.boxValueExpression(key.resolve())], + wtype: new WTuple({ types: [uint64WType, boolWType], immutable: true }), + immediates: [], + sourceLocation, + }), + comment: 'Box must exist', + }), + uint64PType, + ) + } +} +class BoxMapDeleteFunctionBuilder extends BoxMapFunctionBuilderBase { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [key], + } = parseFunctionArgs({ + args, + typeArgs, + funcName: 'BoxMap.delete', + callLocation: sourceLocation, + genericTypeArgs: 0, + argSpec: (a) => [a.required(this.keyType)], + }) + + return new VoidExpressionBuilder( + nodeFactory.stateDelete({ + field: this.boxValueExpression(key.resolve()), + sourceLocation, + wtype: voidWType, + }), + ) + } +} diff --git a/src/awst_build/eb/storage/box/box-ref.ts b/src/awst_build/eb/storage/box/box-ref.ts new file mode 100644 index 00000000..6f44c680 --- /dev/null +++ b/src/awst_build/eb/storage/box/box-ref.ts @@ -0,0 +1,215 @@ +import { nodeFactory } from '../../../../awst/node-factory' +import type { BoxValueExpression, Expression } from '../../../../awst/nodes' +import type { SourceLocation } from '../../../../awst/source-location' +import { boolWType, boxKeyWType, bytesWType, uint64WType, voidWType, WTuple } from '../../../../awst/wtypes' +import { invariant } from '../../../../util' +import type { PType } from '../../../ptypes' +import { boolPType, BoxRefPType, boxRefType, bytesPType, stringPType, uint64PType, voidPType } from '../../../ptypes' +import { instanceEb } from '../../../type-registry' +import { FunctionBuilder, type InstanceBuilder, type NodeBuilder } from '../../index' +import { parseFunctionArgs } from '../../util/arg-parsing' +import { extractKey } from '../util' +import { BoxProxyExpressionBuilder, boxValue, BoxValueExpressionBuilder } from './base' + +export class BoxRefFunctionBuilder extends FunctionBuilder { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [{ key }], + } = parseFunctionArgs({ + args, + typeArgs, + funcName: `BoxRef`, + callLocation: sourceLocation, + genericTypeArgs: 0, + argSpec: (a) => [a.obj({ key: a.required(bytesPType, stringPType) })], + }) + + return new BoxRefExpressionBuilder(extractKey(key, boxKeyWType), boxRefType) + } +} + +export class BoxRefExpressionBuilder extends BoxProxyExpressionBuilder { + constructor(expr: Expression, ptype: PType) { + invariant(ptype instanceof BoxRefPType, 'BoxRefExpressionBuilder must be constructed with ptype of BoxRefPType') + super(expr, ptype) + } + + memberAccess(name: string, sourceLocation: SourceLocation): NodeBuilder { + const boxValueExpr = boxValue({ + key: this._expr, + sourceLocation, + contentType: this.ptype.contentType, + }) + switch (name) { + case 'put': + return new BoxRefPutFunctionBuilder(boxValueExpr) + case 'splice': + return new BoxRefSpliceFunctionBuilder(boxValueExpr) + case 'create': + return new BoxRefCreateFunctionBuilder(boxValueExpr) + case 'extract': + return new BoxRefExtractFunctionBuilder(boxValueExpr) + case 'replace': + return new BoxRefReplaceFunctionBuilder(boxValueExpr) + case 'exists': + case 'length': { + const boxLength = nodeFactory.intrinsicCall({ + opCode: 'box_length', + stackArgs: [boxValueExpr], + wtype: new WTuple({ types: [uint64WType, boolWType], immutable: true }), + immediates: [], + sourceLocation, + }) + if (name === 'exists') { + return instanceEb( + nodeFactory.tupleItemExpression({ + base: boxLength, + sourceLocation, + index: 1n, + }), + boolPType, + ) + } else { + return instanceEb( + nodeFactory.checkedMaybe({ + expr: boxLength, + comment: 'Box must exist', + }), + uint64PType, + ) + } + } + case 'value': + return new BoxValueExpressionBuilder(boxValueExpr, this.ptype.contentType) + } + return super.memberAccess(name, sourceLocation) + } +} + +export abstract class BoxRefBaseFunctionBuilder extends FunctionBuilder { + constructor(protected readonly boxValue: BoxValueExpression) { + super(boxValue.sourceLocation) + } +} + +export class BoxRefCreateFunctionBuilder extends BoxRefBaseFunctionBuilder { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [{ size }], + } = parseFunctionArgs({ + args, + typeArgs, + genericTypeArgs: 0, + funcName: 'BoxRef.create', + callLocation: sourceLocation, + argSpec: (a) => [a.obj({ size: a.required(uint64PType) })], + }) + return instanceEb( + nodeFactory.intrinsicCall({ + opCode: 'box_create', + stackArgs: [this.boxValue, size.resolve()], + wtype: boolWType, + immediates: [], + sourceLocation, + }), + boolPType, + ) + } +} +export class BoxRefExtractFunctionBuilder extends BoxRefBaseFunctionBuilder { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [start, length], + } = parseFunctionArgs({ + args, + typeArgs, + genericTypeArgs: 0, + funcName: 'BoxRef.extract', + callLocation: sourceLocation, + argSpec: (a) => [a.required(uint64PType), a.required(uint64PType)], + }) + return instanceEb( + nodeFactory.intrinsicCall({ + opCode: 'box_extract', + stackArgs: [this.boxValue, start.resolve(), length.resolve()], + wtype: bytesWType, + immediates: [], + sourceLocation, + }), + bytesPType, + ) + } +} +export class BoxRefReplaceFunctionBuilder extends BoxRefBaseFunctionBuilder { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [start, value], + } = parseFunctionArgs({ + args, + typeArgs, + genericTypeArgs: 0, + funcName: 'BoxRef.replace', + callLocation: sourceLocation, + argSpec: (a) => [a.required(uint64PType), a.required(bytesPType)], + }) + return instanceEb( + nodeFactory.intrinsicCall({ + opCode: 'box_replace', + stackArgs: [this.boxValue, start.resolve(), value.resolve()], + wtype: voidWType, + immediates: [], + sourceLocation, + }), + voidPType, + ) + } +} + +export class BoxRefPutFunctionBuilder extends BoxRefBaseFunctionBuilder { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [value], + } = parseFunctionArgs({ + args, + typeArgs, + genericTypeArgs: 0, + funcName: 'BoxRef.put', + callLocation: sourceLocation, + argSpec: (a) => [a.required(bytesPType)], + }) + return instanceEb( + nodeFactory.intrinsicCall({ + opCode: 'box_put', + stackArgs: [this.boxValue, value.resolve()], + wtype: voidWType, + immediates: [], + sourceLocation, + }), + voidPType, + ) + } +} +export class BoxRefSpliceFunctionBuilder extends BoxRefBaseFunctionBuilder { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [start, stop, value], + } = parseFunctionArgs({ + args, + typeArgs, + genericTypeArgs: 0, + funcName: 'BoxRef.splice', + callLocation: sourceLocation, + argSpec: (a) => [a.required(uint64PType), a.required(uint64PType), a.required(bytesPType)], + }) + return instanceEb( + nodeFactory.intrinsicCall({ + opCode: 'box_splice', + stackArgs: [this.boxValue, start.resolve(), stop.resolve(), value.resolve()], + wtype: voidWType, + immediates: [], + sourceLocation, + }), + voidPType, + ) + } +} diff --git a/src/awst_build/eb/storage/box/box.ts b/src/awst_build/eb/storage/box/box.ts new file mode 100644 index 00000000..e929e5f7 --- /dev/null +++ b/src/awst_build/eb/storage/box/box.ts @@ -0,0 +1,163 @@ +import { nodeFactory } from '../../../../awst/node-factory' +import type { BoxValueExpression, Expression } from '../../../../awst/nodes' +import type { SourceLocation } from '../../../../awst/source-location' +import { boolWType, boxKeyWType, uint64WType, voidWType, WTuple } from '../../../../awst/wtypes' +import { invariant } from '../../../../util' +import type { PType } from '../../../ptypes' +import { boolPType, BoxPType, bytesPType, stringPType, TuplePType, uint64PType } from '../../../ptypes' +import { instanceEb } from '../../../type-registry' +import { BooleanExpressionBuilder } from '../../boolean-expression-builder' +import { FunctionBuilder, type InstanceBuilder, type NodeBuilder, ParameterlessFunctionBuilder } from '../../index' +import { parseFunctionArgs } from '../../util/arg-parsing' +import { VoidExpressionBuilder } from '../../void-expression-builder' +import { extractKey } from '../util' +import { BoxProxyExpressionBuilder, boxValue, BoxValueExpressionBuilder } from './base' + +export class BoxFunctionBuilder extends FunctionBuilder { + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + ptypes: [contentPType], + args: [{ key }], + } = parseFunctionArgs({ + args, + typeArgs, + funcName: `Box`, + callLocation: sourceLocation, + genericTypeArgs: 1, + argSpec: (a) => [a.obj({ key: a.required(bytesPType, stringPType) })], + }) + + const ptype = new BoxPType({ content: contentPType }) + return new BoxExpressionBuilder(extractKey(key, boxKeyWType), ptype) + } +} + +export class BoxExpressionBuilder extends BoxProxyExpressionBuilder { + constructor(expr: Expression, ptype: PType) { + invariant(ptype instanceof BoxPType, 'BoxExpressionBuilder must be constructed with ptype of BoxPType') + super(expr, ptype) + } + + memberAccess(name: string, sourceLocation: SourceLocation): NodeBuilder { + const boxValueExpr = boxValue({ + key: this._expr, + sourceLocation, + contentType: this.ptype.contentType, + }) + switch (name) { + case 'value': + return new BoxValueExpressionBuilder(boxValueExpr, this.ptype.contentType) + case 'exists': + return new BooleanExpressionBuilder( + nodeFactory.stateExists({ + field: boxValueExpr, + sourceLocation, + wtype: boolWType, + }), + ) + case 'length': + return instanceEb( + nodeFactory.checkedMaybe({ + expr: nodeFactory.intrinsicCall({ + opCode: 'box_length', + stackArgs: [boxValueExpr], + wtype: new WTuple({ types: [uint64WType, boolWType], immutable: true }), + immediates: [], + sourceLocation, + }), + comment: 'Box must exist', + }), + uint64PType, + ) + case 'delete': + return new BoxDeleteFunctionBuilder(boxValueExpr, sourceLocation) + case 'get': + return new BoxGetFunctionBuilder(boxValueExpr, this.ptype.contentType, sourceLocation) + case 'maybe': + return new BoxMaybeFunctionBuilder(boxValueExpr, this.ptype.contentType, sourceLocation) + } + return super.memberAccess(name, sourceLocation) + } +} + +class BoxDeleteFunctionBuilder extends ParameterlessFunctionBuilder { + constructor(boxValue: BoxValueExpression, sourceLocation: SourceLocation) { + super( + boxValue, + (expr) => + new VoidExpressionBuilder( + nodeFactory.stateDelete({ + sourceLocation, + field: boxValue, + wtype: voidWType, + }), + ), + ) + } +} + +class BoxGetFunctionBuilder extends FunctionBuilder { + constructor( + private readonly boxValue: BoxValueExpression, + private readonly contentType: PType, + sourceLocation: SourceLocation, + ) { + super(sourceLocation) + } + + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [{ default: defaultValue }], + } = parseFunctionArgs({ + args, + typeArgs, + funcName: 'Box.get', + callLocation: sourceLocation, + genericTypeArgs: 0, + argSpec: (a) => [a.obj({ default: a.optional(this.contentType) })], + }) + + if (defaultValue) { + return instanceEb( + nodeFactory.stateGet({ + sourceLocation, + default: defaultValue.resolve(), + wtype: this.contentType.wtypeOrThrow, + field: this.boxValue, + }), + this.contentType, + ) + } else { + return new BoxValueExpressionBuilder(this.boxValue, this.contentType) + } + } +} +class BoxMaybeFunctionBuilder extends FunctionBuilder { + constructor( + private readonly boxValue: BoxValueExpression, + private readonly contentType: PType, + sourceLocation: SourceLocation, + ) { + super(sourceLocation) + } + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + parseFunctionArgs({ + args, + typeArgs, + funcName: 'Box.maybe', + callLocation: sourceLocation, + genericTypeArgs: 0, + argSpec: () => [], + }) + const type = new TuplePType({ items: [this.contentType, boolPType], immutable: true }) + + return instanceEb( + nodeFactory.stateGetEx({ + sourceLocation, + wtype: type.wtype, + field: this.boxValue, + }), + type, + ) + } +} diff --git a/src/awst_build/eb/storage/box/index.ts b/src/awst_build/eb/storage/box/index.ts new file mode 100644 index 00000000..4f4e9180 --- /dev/null +++ b/src/awst_build/eb/storage/box/index.ts @@ -0,0 +1,4 @@ +export { BoxFunctionBuilder, BoxExpressionBuilder } from './box' +export { BoxMapFunctionBuilder, BoxMapExpressionBuilder } from './box-map' +export { BoxRefFunctionBuilder, BoxRefExpressionBuilder } from './box-ref' +export { BoxProxyExpressionBuilder } from './base' diff --git a/src/awst_build/type-resolver.ts b/src/awst_build/type-resolver.ts index fa58219d..e7bf3efd 100644 --- a/src/awst_build/type-resolver.ts +++ b/src/awst_build/type-resolver.ts @@ -74,7 +74,7 @@ export class TypeResolver { resolve(node: ts.Node, sourceLocation: SourceLocation): PType { const symbol = this.getUnaliasedSymbolForNode(node) - if (symbol !== undefined) { + if (symbol !== undefined && symbol.declarations?.length) { const symbolName = symbol && this.getSymbolFullName(symbol, sourceLocation) if (symbolName.name === '*') { return new NamespacePType(symbolName) diff --git a/tests/approvals/box-proxies.algo.ts b/tests/approvals/box-proxies.algo.ts index c719ff8b..8b7d812d 100644 --- a/tests/approvals/box-proxies.algo.ts +++ b/tests/approvals/box-proxies.algo.ts @@ -1,4 +1,4 @@ -import type { bytes } from '@algorandfoundation/algorand-typescript' +import type { bytes, uint64 } from '@algorandfoundation/algorand-typescript' import { assert, Box, BoxMap, BoxRef, Bytes } from '@algorandfoundation/algorand-typescript' const boxA = Box({ key: Bytes('A') }) @@ -10,6 +10,8 @@ function testBox(box: Box, value: string) { assert(box.exists && boxA.exists) + assert(box.length) + box.delete() boxA.delete() assert(!box.exists && !boxA.exists) @@ -30,6 +32,10 @@ function testBoxMap(box: BoxMap, key: string, value: bytes) { box.set(key, value) boxMap.set(key, value) + assert(box.length(key)) + + assert(box.maybe(key)[1]) + assert(box.get(key) === boxMap.get(key)) box.delete(key) @@ -39,7 +45,10 @@ function testBoxMap(box: BoxMap, key: string, value: bytes) { const boxRef = BoxRef({ key: 'abc' }) -function testBoxRef(box: BoxRef) { +function testBoxRef(box: BoxRef, length: uint64) { + if (!boxRef.exists && boxRef.length !== length) { + boxRef.create({ size: 1000 }) + } const someBytes = Bytes.fromHex('FFFFFFFF') box.put(someBytes) boxRef.put(someBytes) diff --git a/tests/approvals/out/box-proxies.awst b/tests/approvals/out/box-proxies.awst index b4c1665f..e3d57b78 100644 --- a/tests/approvals/out/box-proxies.awst +++ b/tests/approvals/out/box-proxies.awst @@ -4,6 +4,7 @@ subroutine testBox(box: box_key, value: string): void var Box["A"].value: string = value assert(box.value == Box["A"].value) assert(STATE_EXISTS(box.value) and STATE_EXISTS(Box["A"].value)) + assert(Boolean(checked_maybe(box_length(box.value), comment=Box must exist))) STATE_DEL(box.value) STATE_DEL(Box["A"].value) assert(!STATE_EXISTS(box.value) and !STATE_EXISTS(Box["A"].value)) @@ -19,16 +20,21 @@ subroutine testBoxMap(box: box_key, key: string, value: bytes): void { var concat(box, reinterpret_cast(key)).value: bytes = value var concat("", reinterpret_cast(key)).value: bytes = value + assert(Boolean(checked_maybe(box_length(concat(box, reinterpret_cast(key)).value), comment=Box must exist))) + assert(STATE_GET_EX(concat(box, reinterpret_cast(key)).value).1) assert(concat(box, reinterpret_cast(key)).value == concat("", reinterpret_cast(key)).value) STATE_DEL(concat(box, reinterpret_cast(key)).value) assert(STATE_GET(concat(box, reinterpret_cast("" + key + "x")).value, default="b") == STATE_GET(concat("", reinterpret_cast("" + key + "x")).value, default="b")) } -subroutine testBoxRef(box: box_key): void +subroutine testBoxRef(box: box_key, length: uint64): void { - var someBytes: bytes = 0x0f0f0f0f + if (!box_length(Box["abc"].value).1 and checked_maybe(box_length(Box["abc"].value), comment=Box must exist) != length) { + box_create(Box["abc"].value, 1000) + } + var someBytes: bytes = 0xffffffff box_put(box.value, someBytes) box_put(Box["abc"].value, someBytes) box_splice(box.value, 1, 2, 0x00) box_splice(Box["abc"].value, 1, 2, 0x00) - assert(box.value == 0x0f000f0f) + assert(box.value == 0xff00ffff) } \ No newline at end of file diff --git a/tests/approvals/out/box-proxies.awst.json b/tests/approvals/out/box-proxies.awst.json index 295d6464..5697ecfc 100644 --- a/tests/approvals/out/box-proxies.awst.json +++ b/tests/approvals/out/box-proxies.awst.json @@ -4,7 +4,7 @@ "source_location": { "file": "tests/approvals/box-proxies.algo.ts", "line": 5, - "end_line": 25, + "end_line": 27, "column": 0, "end_column": 1 }, @@ -58,7 +58,7 @@ "source_location": { "file": "tests/approvals/box-proxies.algo.ts", "line": 5, - "end_line": 25, + "end_line": 27, "column": 50, "end_column": 1 }, @@ -479,15 +479,156 @@ "line": 13, "end_line": 13, "column": 2, - "end_column": 12 + "end_column": 20 }, "expr": { - "_type": "StateDelete", + "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", "line": 13, "end_line": 13, "column": 2, + "end_column": 20 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "op_code": "assert", + "immediates": [], + "stack_args": [ + { + "_type": "ReinterpretCast", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 13, + "end_line": 13, + "column": 2, + "end_column": 20 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "expr": { + "_type": "CheckedMaybe", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 13, + "end_line": 13, + "column": 9, + "end_column": 19 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 13, + "end_line": 13, + "column": 9, + "end_column": 19 + }, + "wtype": { + "_type": "WTuple", + "name": "WTuple", + "immutable": true, + "ephemeral": false, + "scalar_type": null, + "types": [ + { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + } + ] + }, + "op_code": "box_length", + "immediates": [], + "stack_args": [ + { + "_type": "BoxValueExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 13, + "end_line": 13, + "column": 9, + "end_column": 19 + }, + "wtype": { + "_type": "WType", + "name": "string", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "key": { + "_type": "VarExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 13, + "end_line": 13, + "column": 9, + "end_column": 12 + }, + "wtype": { + "_type": "WType", + "name": "box_key", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "name": "box" + }, + "exists_assertion_message": "Box must have value" + } + ], + "comment": null + }, + "comment": "Box must exist" + } + } + ], + "comment": null + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 15, + "end_line": 15, + "column": 2, + "end_column": 12 + }, + "expr": { + "_type": "StateDelete", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 15, + "end_line": 15, + "column": 2, "end_column": 12 }, "wtype": { @@ -501,8 +642,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 13, - "end_line": 13, + "line": 15, + "end_line": 15, "column": 2, "end_column": 12 }, @@ -517,8 +658,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 13, - "end_line": 13, + "line": 15, + "end_line": 15, "column": 2, "end_column": 5 }, @@ -539,8 +680,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 14, - "end_line": 14, + "line": 16, + "end_line": 16, "column": 2, "end_column": 13 }, @@ -548,8 +689,8 @@ "_type": "StateDelete", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 14, - "end_line": 14, + "line": 16, + "end_line": 16, "column": 2, "end_column": 13 }, @@ -564,8 +705,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 14, - "end_line": 14, + "line": 16, + "end_line": 16, "column": 2, "end_column": 13 }, @@ -603,8 +744,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 15, - "end_line": 15, + "line": 17, + "end_line": 17, "column": 2, "end_column": 37 }, @@ -612,8 +753,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 15, - "end_line": 15, + "line": 17, + "end_line": 17, "column": 2, "end_column": 37 }, @@ -631,8 +772,8 @@ "_type": "BooleanBinaryOperation", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 15, - "end_line": 15, + "line": 17, + "end_line": 17, "column": 9, "end_column": 36 }, @@ -647,8 +788,8 @@ "_type": "Not", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 15, - "end_line": 15, + "line": 17, + "end_line": 17, "column": 9, "end_column": 20 }, @@ -663,8 +804,8 @@ "_type": "StateExists", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 15, - "end_line": 15, + "line": 17, + "end_line": 17, "column": 10, "end_column": 20 }, @@ -679,8 +820,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 15, - "end_line": 15, + "line": 17, + "end_line": 17, "column": 10, "end_column": 20 }, @@ -695,8 +836,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 15, - "end_line": 15, + "line": 17, + "end_line": 17, "column": 10, "end_column": 13 }, @@ -718,8 +859,8 @@ "_type": "Not", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 15, - "end_line": 15, + "line": 17, + "end_line": 17, "column": 24, "end_column": 36 }, @@ -734,8 +875,8 @@ "_type": "StateExists", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 15, - "end_line": 15, + "line": 17, + "end_line": 17, "column": 25, "end_column": 36 }, @@ -750,8 +891,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 15, - "end_line": 15, + "line": 17, + "end_line": 17, "column": 25, "end_column": 36 }, @@ -794,8 +935,8 @@ "_type": "AssignmentStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 17, - "end_line": 17, + "line": 19, + "end_line": 19, "column": 8, "end_column": 24 }, @@ -803,8 +944,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 17, - "end_line": 17, + "line": 19, + "end_line": 19, "column": 8, "end_column": 18 }, @@ -821,8 +962,8 @@ "_type": "StringConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 17, - "end_line": 17, + "line": 19, + "end_line": 19, "column": 21, "end_column": 24 }, @@ -840,8 +981,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 18, - "end_line": 18, + "line": 20, + "end_line": 20, "column": 2, "end_column": 80 }, @@ -849,8 +990,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 18, - "end_line": 18, + "line": 20, + "end_line": 20, "column": 2, "end_column": 80 }, @@ -868,8 +1009,8 @@ "_type": "BytesComparisonExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 18, - "end_line": 18, + "line": 20, + "end_line": 20, "column": 9, "end_column": 79 }, @@ -884,8 +1025,8 @@ "_type": "StateGet", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 18, - "end_line": 18, + "line": 20, + "end_line": 20, "column": 9, "end_column": 42 }, @@ -900,8 +1041,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 18, - "end_line": 18, + "line": 20, + "end_line": 20, "column": 9, "end_column": 17 }, @@ -937,8 +1078,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 18, - "end_line": 18, + "line": 20, + "end_line": 20, "column": 29, "end_column": 39 }, @@ -957,8 +1098,8 @@ "_type": "StateGet", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 18, - "end_line": 18, + "line": 20, + "end_line": 20, "column": 47, "end_column": 79 }, @@ -973,8 +1114,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 18, - "end_line": 18, + "line": 20, + "end_line": 20, "column": 47, "end_column": 54 }, @@ -989,8 +1130,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 18, - "end_line": 18, + "line": 20, + "end_line": 20, "column": 47, "end_column": 50 }, @@ -1009,8 +1150,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 18, - "end_line": 18, + "line": 20, + "end_line": 20, "column": 66, "end_column": 76 }, @@ -1033,8 +1174,8 @@ "_type": "AssignmentStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 20, - "end_line": 20, + "line": 22, + "end_line": 22, "column": 6, "end_column": 25 }, @@ -1042,8 +1183,8 @@ "_type": "TupleExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 20, - "end_line": 20, + "line": 22, + "end_line": 22, "column": 6, "end_column": 25 }, @@ -1075,8 +1216,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 20, - "end_line": 20, + "line": 22, + "end_line": 22, "column": 6, "end_column": 25 }, @@ -1093,8 +1234,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 20, - "end_line": 20, + "line": 22, + "end_line": 22, "column": 9, "end_column": 10 }, @@ -1113,8 +1254,8 @@ "_type": "StateGetEx", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 20, - "end_line": 20, + "line": 22, + "end_line": 22, "column": 14, "end_column": 25 }, @@ -1145,8 +1286,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 20, - "end_line": 20, + "line": 22, + "end_line": 22, "column": 14, "end_column": 23 }, @@ -1161,8 +1302,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 20, - "end_line": 20, + "line": 22, + "end_line": 22, "column": 14, "end_column": 17 }, @@ -1183,8 +1324,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 21, - "end_line": 21, + "line": 23, + "end_line": 23, "column": 2, "end_column": 12 }, @@ -1192,8 +1333,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 21, - "end_line": 21, + "line": 23, + "end_line": 23, "column": 2, "end_column": 12 }, @@ -1211,8 +1352,8 @@ "_type": "Not", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 21, - "end_line": 21, + "line": 23, + "end_line": 23, "column": 9, "end_column": 11 }, @@ -1227,8 +1368,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 21, - "end_line": 21, + "line": 23, + "end_line": 23, "column": 10, "end_column": 11 }, @@ -1250,8 +1391,8 @@ "_type": "AssignmentStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 22, - "end_line": 22, + "line": 24, + "end_line": 24, "column": 2, "end_column": 19 }, @@ -1259,8 +1400,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 22, - "end_line": 22, + "line": 24, + "end_line": 24, "column": 2, "end_column": 11 }, @@ -1275,8 +1416,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 22, - "end_line": 22, + "line": 24, + "end_line": 24, "column": 2, "end_column": 5 }, @@ -1295,8 +1436,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 22, - "end_line": 22, + "line": 24, + "end_line": 24, "column": 14, "end_column": 19 }, @@ -1314,8 +1455,8 @@ "_type": "AssignmentStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 23, - "end_line": 23, + "line": 25, + "end_line": 25, "column": 3, "end_column": 22 }, @@ -1323,8 +1464,8 @@ "_type": "TupleExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 23, - "end_line": 23, + "line": 25, + "end_line": 25, "column": 3, "end_column": 22 }, @@ -1356,8 +1497,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 23, - "end_line": 23, + "line": 25, + "end_line": 25, "column": 3, "end_column": 22 }, @@ -1374,8 +1515,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 23, - "end_line": 23, + "line": 25, + "end_line": 25, "column": 6, "end_column": 7 }, @@ -1394,8 +1535,8 @@ "_type": "StateGetEx", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 23, - "end_line": 23, + "line": 25, + "end_line": 25, "column": 11, "end_column": 22 }, @@ -1426,8 +1567,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 23, - "end_line": 23, + "line": 25, + "end_line": 25, "column": 11, "end_column": 20 }, @@ -1442,8 +1583,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 23, - "end_line": 23, + "line": 25, + "end_line": 25, "column": 11, "end_column": 14 }, @@ -1464,8 +1605,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 24, - "end_line": 24, + "line": 26, + "end_line": 26, "column": 2, "end_column": 11 }, @@ -1473,8 +1614,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 24, - "end_line": 24, + "line": 26, + "end_line": 26, "column": 2, "end_column": 11 }, @@ -1492,8 +1633,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 24, - "end_line": 24, + "line": 26, + "end_line": 26, "column": 9, "end_column": 10 }, @@ -1527,8 +1668,8 @@ "_type": "Subroutine", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 29, - "end_line": 38, + "line": 31, + "end_line": 44, "column": 0, "end_column": 1 }, @@ -1545,8 +1686,8 @@ }, "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 29, - "end_line": 29, + "line": 31, + "end_line": 31, "column": 20, "end_column": 46 } @@ -1563,8 +1704,8 @@ }, "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 29, - "end_line": 29, + "line": 31, + "end_line": 31, "column": 48, "end_column": 59 } @@ -1581,8 +1722,8 @@ }, "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 29, - "end_line": 29, + "line": 31, + "end_line": 31, "column": 61, "end_column": 73 } @@ -1599,8 +1740,8 @@ "_type": "Block", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 29, - "end_line": 38, + "line": 31, + "end_line": 44, "column": 75, "end_column": 1 }, @@ -1609,8 +1750,8 @@ "_type": "AssignmentStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 30, - "end_line": 30, + "line": 32, + "end_line": 32, "column": 2, "end_column": 21 }, @@ -1618,8 +1759,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 30, - "end_line": 30, + "line": 32, + "end_line": 32, "column": 2, "end_column": 9 }, @@ -1634,8 +1775,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 30, - "end_line": 30, + "line": 32, + "end_line": 32, "column": 2, "end_column": 9 }, @@ -1653,8 +1794,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 30, - "end_line": 30, + "line": 32, + "end_line": 32, "column": 2, "end_column": 5 }, @@ -1671,8 +1812,8 @@ "_type": "ReinterpretCast", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 30, - "end_line": 30, + "line": 32, + "end_line": 32, "column": 2, "end_column": 9 }, @@ -1687,8 +1828,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 30, - "end_line": 30, + "line": 32, + "end_line": 32, "column": 10, "end_column": 13 }, @@ -1711,8 +1852,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 30, - "end_line": 30, + "line": 32, + "end_line": 32, "column": 15, "end_column": 20 }, @@ -1730,8 +1871,8 @@ "_type": "AssignmentStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 31, - "end_line": 31, + "line": 33, + "end_line": 33, "column": 2, "end_column": 24 }, @@ -1739,8 +1880,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 31, - "end_line": 31, + "line": 33, + "end_line": 33, "column": 2, "end_column": 12 }, @@ -1755,8 +1896,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 31, - "end_line": 31, + "line": 33, + "end_line": 33, "column": 2, "end_column": 12 }, @@ -1774,8 +1915,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 27, - "end_line": 27, + "line": 29, + "end_line": 29, "column": 50, "end_column": 52 }, @@ -1793,8 +1934,8 @@ "_type": "ReinterpretCast", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 31, - "end_line": 31, + "line": 33, + "end_line": 33, "column": 2, "end_column": 12 }, @@ -1809,8 +1950,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 31, - "end_line": 31, + "line": 33, + "end_line": 33, "column": 13, "end_column": 16 }, @@ -1833,8 +1974,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 31, - "end_line": 31, + "line": 33, + "end_line": 33, "column": 18, "end_column": 23 }, @@ -1852,19 +1993,19 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, + "line": 35, + "end_line": 35, "column": 2, - "end_column": 42 + "end_column": 25 }, "expr": { "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, + "line": 35, + "end_line": 35, "column": 2, - "end_column": 42 + "end_column": 25 }, "wtype": { "_type": "WType", @@ -1877,13 +2018,13 @@ "immediates": [], "stack_args": [ { - "_type": "BytesComparisonExpression", + "_type": "ReinterpretCast", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, - "column": 9, - "end_column": 41 + "line": 35, + "end_line": 35, + "column": 2, + "end_column": 25 }, "wtype": { "_type": "WType", @@ -1892,47 +2033,421 @@ "ephemeral": false, "scalar_type": 2 }, - "lhs": { - "_type": "BoxValueExpression", + "expr": { + "_type": "CheckedMaybe", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, + "line": 35, + "end_line": 35, "column": 9, - "end_column": 16 + "end_column": 24 }, "wtype": { "_type": "WType", - "name": "bytes", + "name": "uint64", "immutable": true, "ephemeral": false, - "scalar_type": 1 + "scalar_type": 2 }, - "key": { + "expr": { "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, + "line": 35, + "end_line": 35, "column": 9, - "end_column": 16 + "end_column": 24 }, "wtype": { - "_type": "WType", - "name": "box_key", + "_type": "WTuple", + "name": "WTuple", "immutable": true, "ephemeral": false, - "scalar_type": 1 - }, - "op_code": "concat", - "immediates": [], - "stack_args": [ - { - "_type": "VarExpression", - "source_location": { - "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, + "scalar_type": null, + "types": [ + { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + } + ] + }, + "op_code": "box_length", + "immediates": [], + "stack_args": [ + { + "_type": "BoxValueExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 35, + "end_line": 35, + "column": 9, + "end_column": 19 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "key": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 35, + "end_line": 35, + "column": 9, + "end_column": 19 + }, + "wtype": { + "_type": "WType", + "name": "box_key", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "op_code": "concat", + "immediates": [], + "stack_args": [ + { + "_type": "VarExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 35, + "end_line": 35, + "column": 9, + "end_column": 12 + }, + "wtype": { + "_type": "WType", + "name": "box_key", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "name": "box" + }, + { + "_type": "ReinterpretCast", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 35, + "end_line": 35, + "column": 9, + "end_column": 19 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "expr": { + "_type": "VarExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 35, + "end_line": 35, + "column": 20, + "end_column": 23 + }, + "wtype": { + "_type": "WType", + "name": "string", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "name": "key" + } + } + ], + "comment": null + }, + "exists_assertion_message": "Box must have value" + } + ], + "comment": null + }, + "comment": "Box must exist" + } + } + ], + "comment": null + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 37, + "end_line": 37, + "column": 2, + "end_column": 27 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 37, + "end_line": 37, + "column": 2, + "end_column": 27 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "op_code": "assert", + "immediates": [], + "stack_args": [ + { + "_type": "TupleItemExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 37, + "end_line": 37, + "column": 9, + "end_column": 26 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "base": { + "_type": "StateGetEx", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 37, + "end_line": 37, + "column": 9, + "end_column": 23 + }, + "wtype": { + "_type": "WTuple", + "name": "WTuple", + "immutable": true, + "ephemeral": false, + "scalar_type": null, + "types": [ + { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + } + ] + }, + "field": { + "_type": "BoxValueExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 37, + "end_line": 37, + "column": 9, + "end_column": 18 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "key": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 37, + "end_line": 37, + "column": 9, + "end_column": 18 + }, + "wtype": { + "_type": "WType", + "name": "box_key", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "op_code": "concat", + "immediates": [], + "stack_args": [ + { + "_type": "VarExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 37, + "end_line": 37, + "column": 9, + "end_column": 12 + }, + "wtype": { + "_type": "WType", + "name": "box_key", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "name": "box" + }, + { + "_type": "ReinterpretCast", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 37, + "end_line": 37, + "column": 9, + "end_column": 18 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "expr": { + "_type": "VarExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 37, + "end_line": 37, + "column": 19, + "end_column": 22 + }, + "wtype": { + "_type": "WType", + "name": "string", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "name": "key" + } + } + ], + "comment": null + }, + "exists_assertion_message": "Box must have value" + } + }, + "index": "1" + } + ], + "comment": null + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 39, + "end_line": 39, + "column": 2, + "end_column": 42 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 39, + "end_line": 39, + "column": 2, + "end_column": 42 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "op_code": "assert", + "immediates": [], + "stack_args": [ + { + "_type": "BytesComparisonExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 39, + "end_line": 39, + "column": 9, + "end_column": 41 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "lhs": { + "_type": "BoxValueExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 39, + "end_line": 39, + "column": 9, + "end_column": 16 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "key": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 39, + "end_line": 39, + "column": 9, + "end_column": 16 + }, + "wtype": { + "_type": "WType", + "name": "box_key", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "op_code": "concat", + "immediates": [], + "stack_args": [ + { + "_type": "VarExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 39, + "end_line": 39, "column": 9, "end_column": 12 }, @@ -1949,8 +2464,8 @@ "_type": "ReinterpretCast", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, + "line": 39, + "end_line": 39, "column": 9, "end_column": 16 }, @@ -1965,8 +2480,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, + "line": 39, + "end_line": 39, "column": 17, "end_column": 20 }, @@ -1990,8 +2505,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, + "line": 39, + "end_line": 39, "column": 26, "end_column": 36 }, @@ -2006,8 +2521,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, + "line": 39, + "end_line": 39, "column": 26, "end_column": 36 }, @@ -2025,8 +2540,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 27, - "end_line": 27, + "line": 29, + "end_line": 29, "column": 50, "end_column": 52 }, @@ -2044,8 +2559,8 @@ "_type": "ReinterpretCast", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, + "line": 39, + "end_line": 39, "column": 26, "end_column": 36 }, @@ -2060,8 +2575,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 33, - "end_line": 33, + "line": 39, + "end_line": 39, "column": 37, "end_column": 40 }, @@ -2089,8 +2604,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 35, - "end_line": 35, + "line": 41, + "end_line": 41, "column": 2, "end_column": 17 }, @@ -2098,8 +2613,8 @@ "_type": "StateDelete", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 35, - "end_line": 35, + "line": 41, + "end_line": 41, "column": 2, "end_column": 17 }, @@ -2114,8 +2629,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 35, - "end_line": 35, + "line": 41, + "end_line": 41, "column": 2, "end_column": 12 }, @@ -2130,8 +2645,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 35, - "end_line": 35, + "line": 41, + "end_line": 41, "column": 2, "end_column": 12 }, @@ -2149,8 +2664,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 35, - "end_line": 35, + "line": 41, + "end_line": 41, "column": 2, "end_column": 5 }, @@ -2167,8 +2682,8 @@ "_type": "ReinterpretCast", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 35, - "end_line": 35, + "line": 41, + "end_line": 41, "column": 2, "end_column": 12 }, @@ -2183,8 +2698,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 35, - "end_line": 35, + "line": 41, + "end_line": 41, "column": 13, "end_column": 16 }, @@ -2209,8 +2724,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 2, "end_column": 104 }, @@ -2218,8 +2733,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 2, "end_column": 104 }, @@ -2237,8 +2752,8 @@ "_type": "BytesComparisonExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 9, "end_column": 103 }, @@ -2253,8 +2768,8 @@ "_type": "StateGet", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 9, "end_column": 52 }, @@ -2269,8 +2784,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 9, "end_column": 16 }, @@ -2285,8 +2800,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 9, "end_column": 16 }, @@ -2304,8 +2819,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 9, "end_column": 12 }, @@ -2322,8 +2837,8 @@ "_type": "ReinterpretCast", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 9, "end_column": 16 }, @@ -2338,8 +2853,8 @@ "_type": "BytesBinaryOperation", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 17, "end_column": 26 }, @@ -2354,8 +2869,8 @@ "_type": "BytesBinaryOperation", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 17, "end_column": 26 }, @@ -2370,8 +2885,8 @@ "_type": "StringConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 17, "end_column": 26 }, @@ -2389,8 +2904,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 20, "end_column": 23 }, @@ -2409,8 +2924,8 @@ "_type": "StringConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 17, "end_column": 26 }, @@ -2434,8 +2949,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 45, "end_column": 48 }, @@ -2455,8 +2970,8 @@ "_type": "StateGet", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 57, "end_column": 103 }, @@ -2471,8 +2986,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 57, "end_column": 67 }, @@ -2487,8 +3002,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 57, "end_column": 67 }, @@ -2506,8 +3021,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 27, - "end_line": 27, + "line": 29, + "end_line": 29, "column": 50, "end_column": 52 }, @@ -2524,9 +3039,9 @@ { "_type": "ReinterpretCast", "source_location": { - "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "file": "tests/approvals/box-proxies.algo.ts", + "line": 43, + "end_line": 43, "column": 57, "end_column": 67 }, @@ -2541,8 +3056,8 @@ "_type": "BytesBinaryOperation", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 68, "end_column": 77 }, @@ -2557,8 +3072,8 @@ "_type": "BytesBinaryOperation", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 68, "end_column": 77 }, @@ -2573,8 +3088,8 @@ "_type": "StringConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 68, "end_column": 77 }, @@ -2592,8 +3107,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 71, "end_column": 74 }, @@ -2612,8 +3127,8 @@ "_type": "StringConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 68, "end_column": 77 }, @@ -2637,8 +3152,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 37, - "end_line": 37, + "line": 43, + "end_line": 43, "column": 96, "end_column": 99 }, @@ -2675,8 +3190,8 @@ "_type": "Subroutine", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 42, - "end_line": 49, + "line": 48, + "end_line": 58, "column": 0, "end_column": 1 }, @@ -2693,11 +3208,29 @@ }, "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 42, - "end_line": 42, + "line": 48, + "end_line": 48, "column": 20, "end_column": 31 } + }, + { + "_type": "SubroutineArgument", + "name": "length", + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 48, + "end_line": 48, + "column": 33, + "end_column": 47 + } } ], "return_type": { @@ -2711,18 +3244,402 @@ "_type": "Block", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 42, - "end_line": 49, - "column": 33, + "line": 48, + "end_line": 58, + "column": 49, "end_column": 1 }, "body": [ + { + "_type": "IfElse", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 51, + "column": 2, + "end_column": 3 + }, + "condition": { + "_type": "BooleanBinaryOperation", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 49, + "column": 6, + "end_column": 48 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "left": { + "_type": "Not", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 49, + "column": 6, + "end_column": 20 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "expr": { + "_type": "TupleItemExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 49, + "column": 7, + "end_column": 20 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "base": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 49, + "column": 7, + "end_column": 20 + }, + "wtype": { + "_type": "WTuple", + "name": "WTuple", + "immutable": true, + "ephemeral": false, + "scalar_type": null, + "types": [ + { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + } + ] + }, + "op_code": "box_length", + "immediates": [], + "stack_args": [ + { + "_type": "BoxValueExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 49, + "column": 7, + "end_column": 20 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "key": { + "_type": "BytesConstant", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 46, + "end_line": 46, + "column": 29, + "end_column": 34 + }, + "wtype": { + "_type": "WType", + "name": "box_key", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "value": "VPaz", + "encoding": "utf8" + }, + "exists_assertion_message": "Box must have value" + } + ], + "comment": null + }, + "index": "1" + } + }, + "op": "and", + "right": { + "_type": "NumericComparisonExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 49, + "column": 24, + "end_column": 48 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "lhs": { + "_type": "CheckedMaybe", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 49, + "column": 24, + "end_column": 37 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 49, + "column": 24, + "end_column": 37 + }, + "wtype": { + "_type": "WTuple", + "name": "WTuple", + "immutable": true, + "ephemeral": false, + "scalar_type": null, + "types": [ + { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + } + ] + }, + "op_code": "box_length", + "immediates": [], + "stack_args": [ + { + "_type": "BoxValueExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 49, + "column": 24, + "end_column": 37 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "key": { + "_type": "BytesConstant", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 46, + "end_line": 46, + "column": 29, + "end_column": 34 + }, + "wtype": { + "_type": "WType", + "name": "box_key", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "value": "VPaz", + "encoding": "utf8" + }, + "exists_assertion_message": "Box must have value" + } + ], + "comment": null + }, + "comment": "Box must exist" + }, + "operator": "!=", + "rhs": { + "_type": "VarExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 49, + "column": 42, + "end_column": 48 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "name": "length" + } + } + }, + "if_branch": { + "_type": "Block", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 51, + "column": 50, + "end_column": 3 + }, + "body": [ + { + "_type": "Block", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 49, + "end_line": 51, + "column": 50, + "end_column": 3 + }, + "body": [ + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 50, + "end_line": 50, + "column": 4, + "end_column": 33 + }, + "expr": { + "_type": "IntrinsicCall", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 50, + "end_line": 50, + "column": 4, + "end_column": 33 + }, + "wtype": { + "_type": "WType", + "name": "bool", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "op_code": "box_create", + "immediates": [], + "stack_args": [ + { + "_type": "BoxValueExpression", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 50, + "end_line": 50, + "column": 4, + "end_column": 17 + }, + "wtype": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "key": { + "_type": "BytesConstant", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 46, + "end_line": 46, + "column": 29, + "end_column": 34 + }, + "wtype": { + "_type": "WType", + "name": "box_key", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 + }, + "value": "VPaz", + "encoding": "utf8" + }, + "exists_assertion_message": "Box must have value" + }, + { + "_type": "IntegerConstant", + "source_location": { + "file": "tests/approvals/box-proxies.algo.ts", + "line": 50, + "end_line": 50, + "column": 26, + "end_column": 30 + }, + "wtype": { + "_type": "WType", + "name": "uint64", + "immutable": true, + "ephemeral": false, + "scalar_type": 2 + }, + "value": "1000", + "teal_alias": null + } + ], + "comment": null + } + } + ], + "label": null, + "comment": null + } + ], + "label": null, + "comment": null + }, + "else_branch": null + }, { "_type": "AssignmentStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 43, - "end_line": 43, + "line": 52, + "end_line": 52, "column": 8, "end_column": 45 }, @@ -2730,8 +3647,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 43, - "end_line": 43, + "line": 52, + "end_line": 52, "column": 8, "end_column": 17 }, @@ -2748,8 +3665,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 43, - "end_line": 43, + "line": 52, + "end_line": 52, "column": 20, "end_column": 45 }, @@ -2760,7 +3677,7 @@ "ephemeral": false, "scalar_type": 1 }, - "value": "4-XFy", + "value": "|NsC0", "encoding": "base16" } }, @@ -2768,8 +3685,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 44, - "end_line": 44, + "line": 53, + "end_line": 53, "column": 2, "end_column": 20 }, @@ -2777,8 +3694,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 44, - "end_line": 44, + "line": 53, + "end_line": 53, "column": 2, "end_column": 20 }, @@ -2796,8 +3713,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 44, - "end_line": 44, + "line": 53, + "end_line": 53, "column": 2, "end_column": 9 }, @@ -2812,8 +3729,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 44, - "end_line": 44, + "line": 53, + "end_line": 53, "column": 2, "end_column": 5 }, @@ -2832,8 +3749,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 44, - "end_line": 44, + "line": 53, + "end_line": 53, "column": 10, "end_column": 19 }, @@ -2854,8 +3771,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 45, - "end_line": 45, + "line": 54, + "end_line": 54, "column": 2, "end_column": 23 }, @@ -2863,8 +3780,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 45, - "end_line": 45, + "line": 54, + "end_line": 54, "column": 2, "end_column": 23 }, @@ -2882,8 +3799,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 45, - "end_line": 45, + "line": 54, + "end_line": 54, "column": 2, "end_column": 12 }, @@ -2898,8 +3815,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 40, - "end_line": 40, + "line": 46, + "end_line": 46, "column": 29, "end_column": 34 }, @@ -2919,8 +3836,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 45, - "end_line": 45, + "line": 54, + "end_line": 54, "column": 13, "end_column": 22 }, @@ -2941,8 +3858,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 46, - "end_line": 46, + "line": 55, + "end_line": 55, "column": 2, "end_column": 39 }, @@ -2950,8 +3867,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 46, - "end_line": 46, + "line": 55, + "end_line": 55, "column": 2, "end_column": 39 }, @@ -2969,8 +3886,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 46, - "end_line": 46, + "line": 55, + "end_line": 55, "column": 2, "end_column": 12 }, @@ -2985,8 +3902,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 46, - "end_line": 46, + "line": 55, + "end_line": 55, "column": 2, "end_column": 5 }, @@ -3005,8 +3922,8 @@ "_type": "IntegerConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 46, - "end_line": 46, + "line": 55, + "end_line": 55, "column": 13, "end_column": 14 }, @@ -3024,8 +3941,8 @@ "_type": "IntegerConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 46, - "end_line": 46, + "line": 55, + "end_line": 55, "column": 16, "end_column": 17 }, @@ -3043,8 +3960,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 46, - "end_line": 46, + "line": 55, + "end_line": 55, "column": 19, "end_column": 38 }, @@ -3066,8 +3983,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 47, - "end_line": 47, + "line": 56, + "end_line": 56, "column": 2, "end_column": 42 }, @@ -3075,8 +3992,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 47, - "end_line": 47, + "line": 56, + "end_line": 56, "column": 2, "end_column": 42 }, @@ -3094,8 +4011,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 47, - "end_line": 47, + "line": 56, + "end_line": 56, "column": 2, "end_column": 15 }, @@ -3110,8 +4027,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 40, - "end_line": 40, + "line": 46, + "end_line": 46, "column": 29, "end_column": 34 }, @@ -3131,8 +4048,8 @@ "_type": "IntegerConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 47, - "end_line": 47, + "line": 56, + "end_line": 56, "column": 16, "end_column": 17 }, @@ -3150,8 +4067,8 @@ "_type": "IntegerConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 47, - "end_line": 47, + "line": 56, + "end_line": 56, "column": 19, "end_column": 20 }, @@ -3169,8 +4086,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 47, - "end_line": 47, + "line": 56, + "end_line": 56, "column": 22, "end_column": 41 }, @@ -3192,8 +4109,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 48, - "end_line": 48, + "line": 57, + "end_line": 57, "column": 2, "end_column": 49 }, @@ -3201,8 +4118,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 48, - "end_line": 48, + "line": 57, + "end_line": 57, "column": 2, "end_column": 49 }, @@ -3220,8 +4137,8 @@ "_type": "BytesComparisonExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 48, - "end_line": 48, + "line": 57, + "end_line": 57, "column": 9, "end_column": 48 }, @@ -3236,8 +4153,8 @@ "_type": "BoxValueExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 48, - "end_line": 48, + "line": 57, + "end_line": 57, "column": 9, "end_column": 18 }, @@ -3252,8 +4169,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 48, - "end_line": 48, + "line": 57, + "end_line": 57, "column": 9, "end_column": 12 }, @@ -3273,8 +4190,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/box-proxies.algo.ts", - "line": 48, - "end_line": 48, + "line": 57, + "end_line": 57, "column": 23, "end_column": 48 }, @@ -3285,7 +4202,7 @@ "ephemeral": false, "scalar_type": 1 }, - "value": "4*(Aj", + "value": "{{a90", "encoding": "base16" } }