From 08912a18a65b4153314d0a3bd21cad98cbc0001e Mon Sep 17 00:00:00 2001 From: Tristan Menzel Date: Wed, 27 Nov 2024 10:50:04 -0800 Subject: [PATCH] feat: support fromBytes and fromLog methods for ARC4Encoded types commit 7492df1ad37888aedc3520af7b995cf357814211 Author: Bobby Lat Date: Wed Nov 27 18:06:01 2024 +0800 chore: update cross-spawn version and vulnerability number to match the report commit 817d0eddec4344668e97bae87340062195236e7f Author: Bobby Lat Date: Wed Nov 27 17:42:48 2024 +0800 chore: update approval output after upgrading puyapy to the latest in main branch commit 6c31fad69dfac050db4fee6116a04695f451cad3 Author: Bobby Lat Date: Wed Nov 27 13:04:47 2024 +0800 refactor: according to review feedback - un-export NativeForArc4Int and CompatForArc4Int types - add code invariant to make sure ptype is actually ARC4EncodedType - rename arc4Prefix to arc4ReturnValuePrefix for clarity - remove extra handling of bytes constant as reinterpretCast does it anyway - remove extra resolveToPType calls commit 1caf84d9bb86cead8bcfbc34d5d81098db0a6e20 Author: Bobby Lat Date: Wed Nov 27 10:21:00 2024 +0800 chore: fix test broken by upgrading puya to version 4.0.0 commit 2f2273e855d71c32866eb95e23013d56cc37d648 Author: Bobby Lat Date: Wed Nov 27 09:35:43 2024 +0800 chore: upgrade localnet images in ci pipline commit 66167f4b655e1e4958ac29634df3e879fe63f712 Author: Bobby Lat Date: Tue Nov 26 14:17:08 2024 +0800 refactor: simplify type info passed to fromBytes and fromLog method commit 72dc26aa2bf575d82a53cb7cfa4ff36d200617dc Author: Bobby Lat Date: Tue Nov 19 15:10:49 2024 +0800 chore: upgrade algots package version commit 0c66e7c956e8600a5da479d757cb932e9aaf3c8f Author: Bobby Lat Date: Tue Nov 19 15:04:21 2024 +0800 chore: fix npm audit vulnerability commit 334848fc6eddb8136c7336005834697b264dabc9 Author: Bobby Lat Date: Tue Nov 12 09:49:09 2024 +0800 refactor: remove n and m parameters from UFixedNxM constructor commit be7cc301be183cdc36f75834e715d8cc1ccea98e Author: Bobby Lat Date: Mon Nov 18 16:36:20 2024 +0800 feat: support fromBytes and fromLog methods for ARC4Encoded types commit 269360a750a23076d9a5c3e3b8fe157064eb26b9 Author: Bobby Lat Date: Mon Nov 18 10:55:34 2024 +0800 feat: support calling equals method of bytes type commit c623cb3b5ccf9806cb6ef0b5bd33238dc7eb86a7 Author: Bobby Lat Date: Mon Nov 11 11:29:10 2024 +0800 refactor: export more arc4 types for stub implementation commit 848216b28fe837c09bddd65488c3ed08303ec6dc Author: Bobby Lat Date: Fri Nov 8 14:42:01 2024 +0800 refactor: export generic PTypes for testing package to capture generic type info commit 4fbcb01374c8b628fb2724cc08c2ba1d8aa7f898 Author: Bobby Lat Date: Fri Nov 8 11:08:51 2024 +0800 fix: LogicSig has been renamed to LogicSigClassModel commit 21e747a11d7c0f5b70c106cee1cf1ecb0a5346cf Merge: ccec8901 9fcfe48a Author: boblat Date: Tue Nov 12 10:51:05 2024 +0800 Merge pull request #45 from algorandfoundation/refactor-export-types refactor: export more PTypes for the testing packageto capture generic type info commit 9fcfe48aa17ea444d3a429042aab9580f13aab9b Author: Bobby Lat Date: Tue Nov 12 10:46:17 2024 +0800 refactor: export more PTypes for the testing packageto capture generict type info --- .github/workflows/ci-all.yml | 3 +- .nsprc | 5 + packages/algo-ts/.nsprc | 3 +- packages/algo-ts/src/arc4/encoded-types.ts | 94 +++- packages/algo-ts/src/impl/primitives.ts | 2 +- src/awst_build/context/awst-build-context.ts | 2 +- src/awst_build/eb/arc4/arrays.ts | 8 +- src/awst_build/eb/arc4/base.ts | 119 +++++- src/awst_build/eb/arc4/bool.ts | 5 +- src/awst_build/eb/arc4/string.ts | 5 +- src/awst_build/eb/arc4/struct.ts | 4 +- src/awst_build/eb/arc4/tuple.ts | 6 +- src/awst_build/eb/arc4/ufixed.ts | 27 +- src/awst_build/eb/arc4/uintn.ts | 23 +- src/awst_build/eb/bytes-expression-builder.ts | 40 +- src/index.ts | 21 +- tests/approvals/arc4-types.algo.ts | 3 +- .../Arc4TypesTestContract.approval.teal | 278 +++++++++++- .../approvals/out/arc4-types/arc4-types.awst | 7 +- .../out/arc4-types/arc4-types.awst.json | 403 +++++++----------- tests/expected-output/arc4-types.algo.ts | 2 +- 21 files changed, 754 insertions(+), 306 deletions(-) diff --git a/.github/workflows/ci-all.yml b/.github/workflows/ci-all.yml index 6b4de180..c9458b6f 100644 --- a/.github/workflows/ci-all.yml +++ b/.github/workflows/ci-all.yml @@ -28,7 +28,6 @@ jobs: diffTextLen=${#diffText} [ $diffTextLen -eq 0 ] && echo 'No changes' || (echo 'ERROR: Code differs to published version. Please bump package version or revert changes'; echo $diffText; exit 1;) - ci-puya-ts: name: 'Build @algorandfoundation/puya-ts' uses: ./.github/workflows/node-ci.yml @@ -48,5 +47,5 @@ jobs: python-version: 3.12.6 pre-test-script: | pipx install algokit --python 3.12.6 - algokit localnet start + algokit localnet reset --update pipx install git+https://github.com/algorandfoundation/puya --python 3.12.6 diff --git a/.nsprc b/.nsprc index 2c63c085..91cdc450 100644 --- a/.nsprc +++ b/.nsprc @@ -1,2 +1,7 @@ { + "1100563": { + "active": true, + "notes": "Waiting for https://github.com/npm/cli/issues/7902 to be resolved", + "expiry": "2024-12-31" + } } diff --git a/packages/algo-ts/.nsprc b/packages/algo-ts/.nsprc index 2c63c085..0967ef42 100644 --- a/packages/algo-ts/.nsprc +++ b/packages/algo-ts/.nsprc @@ -1,2 +1 @@ -{ -} +{} diff --git a/packages/algo-ts/src/arc4/encoded-types.ts b/packages/algo-ts/src/arc4/encoded-types.ts index 9bbc5f7e..850fb02f 100644 --- a/packages/algo-ts/src/arc4/encoded-types.ts +++ b/packages/algo-ts/src/arc4/encoded-types.ts @@ -1,7 +1,8 @@ import { avmError, avmInvariant } from '../impl/errors' import { arrayUtil, BytesCls, getNumber, getUint8Array, isBytes, isUint64 } from '../impl/primitives' -import { biguint, BigUintCompat, Bytes, bytes, BytesBacked, StringCompat, Uint64, uint64, Uint64Compat } from '../primitives' +import { biguint, BigUintCompat, Bytes, bytes, BytesBacked, BytesCompat, StringCompat, Uint64, uint64, Uint64Compat } from '../primitives' import { Account } from '../reference' +import { DeliberateAny } from '../typescript-helpers' import { err } from '../util' export type BitSize = 8 | 16 | 32 | 64 | 128 | 256 | 512 @@ -19,6 +20,14 @@ abstract class ARC4Encoded implements BytesBacked { equals(other: this): boolean { return this.bytes.equals(other.bytes) } + + static fromBytes(this: { new (...args: DeliberateAny): T }, bytes: BytesCompat): T { + throw new Error('todo') + } + + static fromLog(this: { new (...args: DeliberateAny): T }, log: BytesCompat): T { + throw new Error('todo') + } } export class Str extends ARC4Encoded { @@ -41,27 +50,54 @@ export class UintN extends ARC4Encoded { get native(): NativeForArc4Int { throw new Error('TODO') } + + static fromBytes>(this: { new (...args: DeliberateAny): I }, bytes: BytesCompat): I { + throw new Error('todo') + } + + static fromLog>(this: { new (...args: DeliberateAny): I }, log: BytesCompat): I { + throw new Error('todo') + } } export class UFixedNxM extends ARC4Encoded { [TypeProperty]?: `arc4.UFixedNxM<${N}x${M}>` - constructor(v: `${number}.${number}`, n?: N, m?: M) { + constructor(v: `${number}.${number}`) { super() } get native(): NativeForArc4Int { throw new Error('TODO') } -} + static fromBytes>( + this: { new (...args: DeliberateAny): I }, + bytes: BytesCompat, + ): I { + throw new Error('todo') + } + + static fromLog>(this: { new (...args: DeliberateAny): I }, log: BytesCompat): I { + throw new Error('todo') + } +} export class Byte extends UintN<8> { constructor(v?: Uint64Compat) { super(v) } + + static fromBytes(this: { new (...args: DeliberateAny): I }, bytes: BytesCompat): I { + throw new Error('todo') + } + + static fromLog(this: { new (...args: DeliberateAny): I }, log: BytesCompat): I { + throw new Error('todo') + } } -export class Bool { +export class Bool extends ARC4Encoded { [TypeProperty]?: `arc4.Bool` #v: boolean constructor(v?: boolean) { + super() this.#v = v ?? false } @@ -179,8 +215,21 @@ export class StaticArray exte copy(): StaticArray { return new StaticArray(...this.items) } -} + static fromBytes>( + this: { new (...args: DeliberateAny): I }, + bytes: BytesCompat, + ): I { + throw new Error('todo') + } + + static fromLog>( + this: { new (...args: DeliberateAny): I }, + log: BytesCompat, + ): I { + throw new Error('todo') + } +} export class DynamicArray extends Arc4ReadonlyArray { [TypeProperty]?: `arc4.DynamicArray<${TItem[typeof TypeProperty]}>` constructor(...items: TItem[]) { @@ -207,6 +256,14 @@ export class DynamicArray extends Arc4ReadonlyArray { return new DynamicArray(...this.items) } + + static fromBytes>(this: { new (...args: DeliberateAny): I }, bytes: BytesCompat): I { + throw new Error('todo') + } + + static fromLog>(this: { new (...args: DeliberateAny): I }, log: BytesCompat): I { + throw new Error('todo') + } } type ExpandTupleType = T extends [infer T1 extends ARC4Encoded, ...infer TRest extends ARC4Encoded[]] ? TRest extends [] @@ -233,6 +290,20 @@ export class Tuple extends ARC4E get native(): TTuple { return this.#items } + + static fromBytes>( + this: { new (...args: TTuple): I }, + bytes: BytesCompat, + ): I { + throw new Error('todo') + } + + static fromLog>( + this: { new (...args: TTuple): I }, + log: BytesCompat, + ): I { + throw new Error('todo') + } } export class Address extends Arc4ReadonlyArray { @@ -274,9 +345,20 @@ class StructImpl extends StructBase { }) } } + static fromBytes(this: { new (args: T): I }, bytes: BytesCompat): I { + throw new Error('todo') + } + + static fromLog(this: { new (args: T): I }, log: BytesCompat): I { + throw new Error('todo') + } } -type StructConstructor = new (initial: T) => StructBase & T +type StructConstructor = { + new (initial: T): StructBase & T + fromBytes: (bytes: BytesCompat) => StructBase & T + fromLog: (log: BytesCompat) => StructBase & T +} export const Struct = StructImpl as StructConstructor diff --git a/packages/algo-ts/src/impl/primitives.ts b/packages/algo-ts/src/impl/primitives.ts index 687b9ba6..15b3502f 100644 --- a/packages/algo-ts/src/impl/primitives.ts +++ b/packages/algo-ts/src/impl/primitives.ts @@ -243,7 +243,7 @@ export class BytesCls extends AlgoTsPrimitiveCls { return new BytesCls(arrayUtil.arrayAt(this.#v, i)) } - slice(start: undefined | StubUint64Compat, end: undefined | StubUint64Compat): BytesCls { + slice(start?: StubUint64Compat, end?: StubUint64Compat): BytesCls { const sliced = arrayUtil.arraySlice(this.#v, start, end) return new BytesCls(sliced) } diff --git a/src/awst_build/context/awst-build-context.ts b/src/awst_build/context/awst-build-context.ts index f5eff158..022b17e5 100644 --- a/src/awst_build/context/awst-build-context.ts +++ b/src/awst_build/context/awst-build-context.ts @@ -11,13 +11,13 @@ import type { NodeBuilder } from '../eb' import type { AppStorageDeclaration } from '../models/app-storage-declaration' import type { ContractClassModel } from '../models/contract-class-model' import { CompilationSet } from '../models/contract-class-model' +import type { LogicSigClassModel } from '../models/logic-sig-class-model' import type { ContractClassPType, PType } from '../ptypes' import { typeRegistry } from '../type-registry' import { TypeResolver } from '../type-resolver' import { EvaluationContext } from './evaluation-context' import { SwitchLoopContext } from './switch-loop-context' import { UniqueNameResolver } from './unique-name-resolver' -import type { LogicSigClassModel } from '../models/logic-sig-class-model' export interface AwstBuildContext { /** diff --git a/src/awst_build/eb/arc4/arrays.ts b/src/awst_build/eb/arc4/arrays.ts index e075cba2..e2e1e956 100644 --- a/src/awst_build/eb/arc4/arrays.ts +++ b/src/awst_build/eb/arc4/arrays.ts @@ -33,9 +33,9 @@ import { SliceFunctionBuilder } from '../shared/slice-function-builder' import { UInt64ExpressionBuilder } from '../uint64-expression-builder' import { requireExpressionOfType } from '../util' import { parseFunctionArgs } from '../util/arg-parsing' -import { Arc4EncodedBaseExpressionBuilder } from './base' +import { Arc4EncodedBaseClassBuilder, Arc4EncodedBaseExpressionBuilder } from './base' -export class DynamicArrayClassBuilder extends ClassBuilder { +export class DynamicArrayClassBuilder extends Arc4EncodedBaseClassBuilder { readonly ptype = DynamicArrayConstructor newCall(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): InstanceBuilder { @@ -63,7 +63,7 @@ export class DynamicArrayClassBuilder extends ClassBuilder { ) } } -export class StaticArrayClassBuilder extends ClassBuilder { +export class StaticArrayClassBuilder extends Arc4EncodedBaseClassBuilder { readonly ptype = StaticArrayConstructor newCall(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): InstanceBuilder { @@ -105,7 +105,7 @@ export class StaticArrayClassBuilder extends ClassBuilder { ) } } -export class AddressClassBuilder extends ClassBuilder { +export class AddressClassBuilder extends Arc4EncodedBaseClassBuilder { readonly ptype = AddressClass newCall(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): InstanceBuilder { diff --git a/src/awst_build/eb/arc4/base.ts b/src/awst_build/eb/arc4/base.ts index e41c5b19..e726ecb9 100644 --- a/src/awst_build/eb/arc4/base.ts +++ b/src/awst_build/eb/arc4/base.ts @@ -4,15 +4,31 @@ import { EqualityComparison } from '../../../awst/nodes' import type { SourceLocation } from '../../../awst/source-location' import { wtypes } from '../../../awst/wtypes' import { CodeError } from '../../../errors' -import type { PType } from '../../ptypes' -import type { ARC4EncodedType } from '../../ptypes/arc4-types' -import { instanceEb } from '../../type-registry' +import { codeInvariant, hexToUint8Array } from '../../../util' +import { bytesPType, type PType } from '../../ptypes' +import { ARC4EncodedType } from '../../ptypes/arc4-types' +import { instanceEb, typeRegistry } from '../../type-registry' import { BooleanExpressionBuilder } from '../boolean-expression-builder' import { BytesExpressionBuilder } from '../bytes-expression-builder' import type { InstanceBuilder, NodeBuilder } from '../index' -import { BuilderComparisonOp, FunctionBuilder, InstanceExpressionBuilder } from '../index' +import { BuilderComparisonOp, ClassBuilder, FunctionBuilder, InstanceExpressionBuilder } from '../index' import { parseFunctionArgs } from '../util/arg-parsing' +export abstract class Arc4EncodedBaseClassBuilder extends ClassBuilder { + constructor(sourceLocation: SourceLocation) { + super(sourceLocation) + } + memberAccess(name: string, sourceLocation: SourceLocation): NodeBuilder { + switch (name) { + case 'fromBytes': + return new Arc4EncodedFromBytesFunctionBuilder(sourceLocation) + case 'fromLog': + return new Arc4EncodedFromLogFunctionBuilder(sourceLocation) + } + return super.memberAccess(name, sourceLocation) + } +} + export class Arc4EncodedBaseExpressionBuilder extends InstanceExpressionBuilder { constructor(expr: Expression, ptype: T) { super(expr, ptype) @@ -85,3 +101,98 @@ class Arc4EqualsFunctionBuilder extends FunctionBuilder { ) } } + +export class Arc4EncodedFromBytesFunctionBuilder extends FunctionBuilder { + constructor( + sourceLocation: SourceLocation, + private ptypeFactory?: (args: PType[]) => ARC4EncodedType, + private genericArgsCount?: number, + ) { + super(sourceLocation) + } + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const funcName = 'fromBytes' + const { + ptypes, + args: [initialValueBuilder], + } = parseFunctionArgs({ + args, + typeArgs, + genericTypeArgs: this.genericArgsCount ?? 1, + funcName, + argSpec: (a) => [a.required(bytesPType)], + callLocation: sourceLocation, + }) + + const ptype = this.ptypeFactory ? this.ptypeFactory(ptypes) : ptypes[0] + codeInvariant(ptype instanceof ARC4EncodedType, 'Expected ARC4EncodedType') + const initialValue = initialValueBuilder.resolve() + const initialValueExpr = nodeFactory.reinterpretCast({ + wtype: ptype.wtype, + sourceLocation, + expr: initialValue, + }) + + return typeRegistry.getInstanceEb(initialValueExpr, ptype) + } +} + +export class Arc4EncodedFromLogFunctionBuilder extends FunctionBuilder { + constructor( + sourceLocation: SourceLocation, + private ptypeFactory?: (args: PType[]) => ARC4EncodedType, + private genericArgsCount?: number, + ) { + super(sourceLocation) + } + + call(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const funcName = 'fromLog' + const { + ptypes, + args: [initialValueBuilder], + } = parseFunctionArgs({ + args, + typeArgs, + genericTypeArgs: this.genericArgsCount ?? 1, + funcName, + argSpec: (a) => [a.required(bytesPType)], + callLocation: sourceLocation, + }) + + const ptype = this.ptypeFactory ? this.ptypeFactory(ptypes) : ptypes[0] + codeInvariant(ptype instanceof ARC4EncodedType, 'Expected ARC4EncodedType') + const initialValue = initialValueBuilder.resolve() + const arc4Value = nodeFactory.intrinsicCall({ + opCode: 'extract', + immediates: [4n, 0n], + wtype: bytesPType.wtype, + stackArgs: [initialValue], + sourceLocation, + }) + const arc4ValueExpr = nodeFactory.reinterpretCast({ + wtype: ptype.wtype, + sourceLocation, + expr: arc4Value, + }) + const arc4ReturnValuePrefix = nodeFactory.intrinsicCall({ + opCode: 'extract', + immediates: [0n, 4n], + wtype: bytesPType.wtype, + stackArgs: [initialValue], + sourceLocation, + }) + const arc4PrefixIsValid = nodeFactory.bytesComparisonExpression({ + operator: EqualityComparison.eq, + lhs: arc4ReturnValuePrefix, + rhs: nodeFactory.bytesConstant({ value: hexToUint8Array('151F7C75'), sourceLocation }), + sourceLocation, + }) + + const fromLogExpr = nodeFactory.checkedMaybe({ + expr: nodeFactory.tupleExpression({ items: [arc4ValueExpr, arc4PrefixIsValid], sourceLocation }), + comment: 'ARC4 prefix is valid', + }) + return typeRegistry.getInstanceEb(fromLogExpr, ptype) + } +} diff --git a/src/awst_build/eb/arc4/bool.ts b/src/awst_build/eb/arc4/bool.ts index bc3993a4..6bba3f80 100644 --- a/src/awst_build/eb/arc4/bool.ts +++ b/src/awst_build/eb/arc4/bool.ts @@ -3,10 +3,9 @@ import type { SourceLocation } from '../../../awst/source-location' import type { PType } from '../../ptypes' import { ARC4BoolClass, ARC4BooleanType, type ARC4EncodedType } from '../../ptypes/arc4-types' import type { InstanceBuilder, NodeBuilder } from '../index' -import { ClassBuilder } from '../index' -import { Arc4EncodedBaseExpressionBuilder } from './base' +import { Arc4EncodedBaseClassBuilder, Arc4EncodedBaseExpressionBuilder } from './base' -export class BoolClassBuilder extends ClassBuilder { +export class BoolClassBuilder extends Arc4EncodedBaseClassBuilder { readonly ptype = ARC4BoolClass newCall(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): InstanceBuilder { diff --git a/src/awst_build/eb/arc4/string.ts b/src/awst_build/eb/arc4/string.ts index 3425188a..7d0cf882 100644 --- a/src/awst_build/eb/arc4/string.ts +++ b/src/awst_build/eb/arc4/string.ts @@ -8,11 +8,10 @@ import { stringPType } from '../../ptypes' import type { ARC4EncodedType } from '../../ptypes/arc4-types' import { ARC4StrClass, ARC4StringType } from '../../ptypes/arc4-types' import type { InstanceBuilder, NodeBuilder } from '../index' -import { ClassBuilder } from '../index' import { parseFunctionArgs } from '../util/arg-parsing' -import { Arc4EncodedBaseExpressionBuilder } from './base' +import { Arc4EncodedBaseClassBuilder, Arc4EncodedBaseExpressionBuilder } from './base' -export class StrClassBuilder extends ClassBuilder { +export class StrClassBuilder extends Arc4EncodedBaseClassBuilder { readonly ptype = ARC4StrClass newCall(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): InstanceBuilder { diff --git a/src/awst_build/eb/arc4/struct.ts b/src/awst_build/eb/arc4/struct.ts index e9eb476e..4b05d8d4 100644 --- a/src/awst_build/eb/arc4/struct.ts +++ b/src/awst_build/eb/arc4/struct.ts @@ -10,9 +10,9 @@ import { InstanceBuilder } from '../index' import { NodeBuilder } from '../index' import { requireExpressionOfType } from '../util' import { parseFunctionArgs } from '../util/arg-parsing' -import { Arc4EncodedBaseExpressionBuilder } from './base' +import { Arc4EncodedBaseClassBuilder, Arc4EncodedBaseExpressionBuilder } from './base' -export class StructClassBuilder extends NodeBuilder { +export class StructClassBuilder extends Arc4EncodedBaseClassBuilder { readonly ptype: ARC4StructClass constructor(sourceLocation: SourceLocation, ptype: PType) { diff --git a/src/awst_build/eb/arc4/tuple.ts b/src/awst_build/eb/arc4/tuple.ts index 17d634ff..ebade255 100644 --- a/src/awst_build/eb/arc4/tuple.ts +++ b/src/awst_build/eb/arc4/tuple.ts @@ -8,12 +8,12 @@ import { numberPType, TuplePType, uint64PType } from '../../ptypes' import { ARC4EncodedType, Arc4TupleClass, ARC4TupleType } from '../../ptypes/arc4-types' import { instanceEb } from '../../type-registry' import type { InstanceBuilder, NodeBuilder } from '../index' -import { ClassBuilder, FunctionBuilder } from '../index' +import { FunctionBuilder } from '../index' import { requireIntegerConstant } from '../util' import { parseFunctionArgs } from '../util/arg-parsing' -import { Arc4EncodedBaseExpressionBuilder } from './base' +import { Arc4EncodedBaseClassBuilder, Arc4EncodedBaseExpressionBuilder } from './base' -export class Arc4TupleClassBuilder extends ClassBuilder { +export class Arc4TupleClassBuilder extends Arc4EncodedBaseClassBuilder { readonly ptype = Arc4TupleClass newCall(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): InstanceBuilder { diff --git a/src/awst_build/eb/arc4/ufixed.ts b/src/awst_build/eb/arc4/ufixed.ts index 75fe36f3..21a0a208 100644 --- a/src/awst_build/eb/arc4/ufixed.ts +++ b/src/awst_build/eb/arc4/ufixed.ts @@ -4,14 +4,19 @@ import type { SourceLocation } from '../../../awst/source-location' import { CodeError } from '../../../errors' import { codeInvariant, invariant } from '../../../util' import type { PType } from '../../ptypes' -import { numberPType, NumericLiteralPType, stringPType } from '../../ptypes' +import { NumericLiteralPType, stringPType } from '../../ptypes' import { UFixedNxMClass, UFixedNxMType } from '../../ptypes/arc4-types' -import { ClassBuilder, type InstanceBuilder, type NodeBuilder } from '../index' +import { type InstanceBuilder, type NodeBuilder } from '../index' import { isValidLiteralForPType, requireStringConstant } from '../util' import { parseFunctionArgs } from '../util/arg-parsing' -import { Arc4EncodedBaseExpressionBuilder } from './base' +import { + Arc4EncodedBaseClassBuilder, + Arc4EncodedBaseExpressionBuilder, + Arc4EncodedFromBytesFunctionBuilder, + Arc4EncodedFromLogFunctionBuilder, +} from './base' -export class UFixedNxMClassBuilder extends ClassBuilder { +export class UFixedNxMClassBuilder extends Arc4EncodedBaseClassBuilder { readonly ptype = UFixedNxMClass newCall(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): InstanceBuilder { @@ -23,7 +28,7 @@ export class UFixedNxMClassBuilder extends ClassBuilder { typeArgs, genericTypeArgs: 2, funcName: this.typeDescription, - argSpec: (a) => [a.optional(stringPType), a.optional(numberPType), a.optional(numberPType)], + argSpec: (a) => [a.optional(stringPType)], callLocation: sourceLocation, }) codeInvariant( @@ -40,6 +45,18 @@ export class UFixedNxMClassBuilder extends ClassBuilder { return newUFixedNxM(initialValueBuilder, ptype, sourceLocation) } + + memberAccess(name: string, sourceLocation: SourceLocation): NodeBuilder { + const ptypeFactory = (args: PType[]) => + new UFixedNxMType({ n: (args[0] as NumericLiteralPType).literalValue, m: (args[1] as NumericLiteralPType).literalValue }) + switch (name) { + case 'fromBytes': + return new Arc4EncodedFromBytesFunctionBuilder(sourceLocation, ptypeFactory, 2) + case 'fromLog': + return new Arc4EncodedFromLogFunctionBuilder(sourceLocation, ptypeFactory, 2) + } + return super.memberAccess(name, sourceLocation) + } } function newUFixedNxM(initialValue: InstanceBuilder | undefined, ptype: UFixedNxMType, sourceLocation: SourceLocation) { diff --git a/src/awst_build/eb/arc4/uintn.ts b/src/awst_build/eb/arc4/uintn.ts index 9aff589b..8d2af715 100644 --- a/src/awst_build/eb/arc4/uintn.ts +++ b/src/awst_build/eb/arc4/uintn.ts @@ -8,12 +8,16 @@ import type { PType } from '../../ptypes' import { biguintPType, NumericLiteralPType, uint64PType } from '../../ptypes' import { arc4ByteAlias, ByteClass, UintNClass, UintNType } from '../../ptypes/arc4-types' import type { InstanceBuilder, NodeBuilder } from '../index' -import { ClassBuilder } from '../index' import { isValidLiteralForPType } from '../util' import { parseFunctionArgs } from '../util/arg-parsing' -import { Arc4EncodedBaseExpressionBuilder } from './base' +import { + Arc4EncodedBaseClassBuilder, + Arc4EncodedBaseExpressionBuilder, + Arc4EncodedFromBytesFunctionBuilder, + Arc4EncodedFromLogFunctionBuilder, +} from './base' -export class UintNClassBuilder extends ClassBuilder { +export class UintNClassBuilder extends Arc4EncodedBaseClassBuilder { readonly ptype = UintNClass newCall(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): InstanceBuilder { @@ -37,9 +41,20 @@ export class UintNClassBuilder extends ClassBuilder { return newUintN(initialValueBuilder, ptype, sourceLocation) } + + memberAccess(name: string, sourceLocation: SourceLocation): NodeBuilder { + const ptypeFactory = (args: PType[]) => new UintNType({ n: (args[0] as NumericLiteralPType).literalValue }) + switch (name) { + case 'fromBytes': + return new Arc4EncodedFromBytesFunctionBuilder(sourceLocation, ptypeFactory) + case 'fromLog': + return new Arc4EncodedFromLogFunctionBuilder(sourceLocation, ptypeFactory) + } + return super.memberAccess(name, sourceLocation) + } } -export class ByteClassBuilder extends ClassBuilder { +export class ByteClassBuilder extends Arc4EncodedBaseClassBuilder { readonly ptype = ByteClass newCall(args: ReadonlyArray, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): InstanceBuilder { diff --git a/src/awst_build/eb/bytes-expression-builder.ts b/src/awst_build/eb/bytes-expression-builder.ts index 5fd4d885..dc9ac194 100644 --- a/src/awst_build/eb/bytes-expression-builder.ts +++ b/src/awst_build/eb/bytes-expression-builder.ts @@ -3,7 +3,15 @@ import type { awst } from '../../awst' import { intrinsicFactory } from '../../awst/intrinsic-factory' import { nodeFactory } from '../../awst/node-factory' import type { Expression } from '../../awst/nodes' -import { BytesBinaryOperator, BytesConstant, BytesEncoding, BytesUnaryOperator, IntegerConstant, StringConstant } from '../../awst/nodes' +import { + BytesBinaryOperator, + BytesConstant, + BytesEncoding, + BytesUnaryOperator, + EqualityComparison, + IntegerConstant, + StringConstant, +} from '../../awst/nodes' import type { SourceLocation } from '../../awst/source-location' import { wtypes } from '../../awst/wtypes' @@ -22,6 +30,7 @@ import { stringPType, uint64PType, } from '../ptypes' +import { BooleanExpressionBuilder } from './boolean-expression-builder' import type { BuilderComparisonOp, InstanceBuilder, NodeBuilder } from './index' import { BuilderUnaryOp, FunctionBuilder, InstanceExpressionBuilder, ParameterlessFunctionBuilder } from './index' import { ArrayLiteralExpressionBuilder } from './literal/array-literal-expression-builder' @@ -211,6 +220,8 @@ export class BytesExpressionBuilder extends InstanceExpressionBuilder, typeArgs: ReadonlyArray, sourceLocation: SourceLocation): NodeBuilder { + const { + args: [right], + } = parseFunctionArgs({ + args, + typeArgs, + genericTypeArgs: 0, + callLocation: sourceLocation, + funcName: 'equals', + argSpec: (a) => [a.required(bytesPType)], + }) + return new BooleanExpressionBuilder( + nodeFactory.bytesComparisonExpression({ + operator: EqualityComparison.eq, + lhs: this.expr, + rhs: right.resolve(), + sourceLocation, + }), + ) + } +} diff --git a/src/index.ts b/src/index.ts index 9bb9b7e0..b7de1fcb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,7 +24,26 @@ import { } from './util' export { SourceLocation } from './awst/source-location' -export { anyPType, ContractClassPType, FunctionPType, PType } from './awst_build/ptypes' +export { + anyPType, + BoxMapPType, + BoxPType, + ContractClassPType, + FunctionPType, + GlobalStateType, + LocalStateType, + PType, +} from './awst_build/ptypes' +export { + ARC4BooleanType, + ARC4StringType, + ARC4StructType, + ARC4TupleType, + DynamicArrayType, + StaticArrayType, + UFixedNxMType, + UintNType, +} from './awst_build/ptypes/arc4-types' export { registerPTypes } from './awst_build/ptypes/register' export { typeRegistry } from './awst_build/type-registry' export { TypeResolver } from './awst_build/type-resolver' diff --git a/tests/approvals/arc4-types.algo.ts b/tests/approvals/arc4-types.algo.ts index 681cb994..7366db40 100644 --- a/tests/approvals/arc4-types.algo.ts +++ b/tests/approvals/arc4-types.algo.ts @@ -14,7 +14,7 @@ import { } from '@algorandfoundation/algorand-typescript/arc4' function testUFixed() { - const a = new UFixedNxM('1.244', 32, 4) + const a = new UFixedNxM<32, 4>('1.244') const c = new UFixedNxM<32, 4>('1.244') assert(a.equals(c)) @@ -112,6 +112,7 @@ export class Arc4TypesTestContract extends BaseContract { const x = new ARC4Uint64() testStr() test(1, 2n, new UintN<256>(4)) + testUFixed() testByte() testArrays(new UintN<64>(65)) testAddress() diff --git a/tests/approvals/out/arc4-types/Arc4TypesTestContract.approval.teal b/tests/approvals/out/arc4-types/Arc4TypesTestContract.approval.teal index 264ba801..33a95759 100644 --- a/tests/approvals/out/arc4-types/Arc4TypesTestContract.approval.teal +++ b/tests/approvals/out/arc4-types/Arc4TypesTestContract.approval.teal @@ -1,34 +1,130 @@ #pragma version 10 tests/approvals/arc4-types.algo.ts::Arc4TypesTestContract.approvalProgram: - intcblock 1 16 8 0 + intcblock 0 1 8 2 + bytecblock 0x 0x0000 base32(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) 0x00 + txn ApplicationID + bnz main_after_if_else@2 + callsub constructor + +main_after_if_else@2: + // tests/approvals/arc4-types.algo.ts:113 + // testStr() + callsub testStr // tests/approvals/arc4-types.algo.ts:114 // test(1, 2n, new UintN<256>(4)) - intc_0 // 1 - pushbytess 0x02 0x0000000000000000000000000000000000000000000000000000000000000004 // 0x02, 0x0000000000000000000000000000000000000000000000000000000000000004 + intc_1 // 1 + pushbytes 0x02 + pushbytes 0x0000000000000000000000000000000000000000000000000000000000000004 callsub test + // tests/approvals/arc4-types.algo.ts:115 + // testUFixed() + callsub testUFixed // tests/approvals/arc4-types.algo.ts:116 + // testByte() + callsub testByte + // tests/approvals/arc4-types.algo.ts:117 // testArrays(new UintN<64>(65)) pushbytes 0x0000000000000041 callsub testArrays - // tests/approvals/arc4-types.algo.ts:117 + // tests/approvals/arc4-types.algo.ts:118 // testAddress() callsub testAddress + // tests/approvals/arc4-types.algo.ts:119 + // testTuple() + callsub testTuple // tests/approvals/arc4-types.algo.ts:120 + // testUFixed() + callsub testUFixed + // tests/approvals/arc4-types.algo.ts:121 // testDynamicBytes(Bytes('hmmmmmmmmm')) pushbytes "hmmmmmmmmm" callsub testDynamicBytes + // tests/approvals/arc4-types.algo.ts:122 + // testStaticBytes() + callsub testStaticBytes + // tests/approvals/arc4-types.algo.ts:123 + // const result = new arc4.DynamicArray>() + bytec_1 // 0x0000 + bytec_0 // 0x + concat // tests/approvals/arc4-types.algo.ts:124 + // assert(result.length === 0) + intc_0 // 0 + extract_uint16 + intc_0 // 0 + == + assert + // tests/approvals/arc4-types.algo.ts:125 // return true - intc_0 // 1 + intc_1 // 1 return +// tests/approvals/arc4-types.algo.ts::Arc4TypesTestContract.constructor() -> void: +constructor: + // tests/approvals/arc4-types.algo.ts:106 + // export class Arc4TypesTestContract extends BaseContract { + proto 0 0 + retsub + + +// tests/approvals/arc4-types.algo.ts::testStr() -> void: +testStr: + // tests/approvals/arc4-types.algo.ts:41 + // function testStr() { + proto 0 0 + // tests/approvals/arc4-types.algo.ts:42 + // const s1 = new Str() + bytec_1 // 0x0000 + // tests/approvals/arc4-types.algo.ts:43 + // assert(s1.bytes === new UintN<16>(0).bytes, 'Empty string should equal the uint16 length prefix') + dup + == + assert // Empty string should equal the uint16 length prefix + // tests/approvals/arc4-types.algo.ts:44 + // const s2 = new Str('Hello') + pushbytes 0x000548656c6c6f + // tests/approvals/arc4-types.algo.ts:45 + // assert(s2.native === 'Hello') + extract 2 0 + pushbytes "Hello" + == + assert + retsub + + // tests/approvals/arc4-types.algo.ts::test(n: uint64, b: bytes, c: bytes) -> void: test: // tests/approvals/arc4-types.algo.ts:23 // function test(n: uint64, b: biguint, c: UintN<256>) { proto 3 0 + // tests/approvals/arc4-types.algo.ts:24 + // const x = new UintN<8>(4) + pushbytes 0x04 + // tests/approvals/arc4-types.algo.ts:25 + // assert(x.bytes.length === 1) + len + intc_1 // 1 + == + assert + // tests/approvals/arc4-types.algo.ts:26 + // const x2 = new UintN<8>(255n) + pushbytes 0xff + // tests/approvals/arc4-types.algo.ts:27 + // assert(x2.bytes === Bytes.fromHex('ff')) + dup + == + assert + // tests/approvals/arc4-types.algo.ts:29 + // const y = new UintN<16>() + bytec_1 // 0x0000 + // tests/approvals/arc4-types.algo.ts:30 + // assert(y.bytes.length === 2) + len + intc_3 // 2 + == + assert // tests/approvals/arc4-types.algo.ts:31 // const z = new UintN<8>(n) frame_dig -3 @@ -46,10 +142,10 @@ test: // const a = new UintN<128>(b) frame_dig -2 len - intc_1 // 16 + pushint 16 // 16 <= assert // overflow - intc_1 // 16 + pushint 16 // 16 bzero frame_dig -2 b| @@ -68,6 +164,42 @@ test: retsub +// tests/approvals/arc4-types.algo.ts::testUFixed() -> void: +testUFixed: + // tests/approvals/arc4-types.algo.ts:16 + // function testUFixed() { + proto 0 0 + // tests/approvals/arc4-types.algo.ts:17 + // const a = new UFixedNxM<32, 4>('1.244') + pushbytes 0x000004dc + // tests/approvals/arc4-types.algo.ts:18 + // const c = new UFixedNxM<32, 4>('1.244') + dup + // tests/approvals/arc4-types.algo.ts:20 + // assert(a.equals(c)) + == + assert + retsub + + +// tests/approvals/arc4-types.algo.ts::testByte() -> void: +testByte: + // tests/approvals/arc4-types.algo.ts:82 + // function testByte() { + proto 0 0 + // tests/approvals/arc4-types.algo.ts:83 + // const b = new Byte() + bytec_3 // 0x00 + // tests/approvals/arc4-types.algo.ts:84 + // const b2 = new Byte(0) + dup + // tests/approvals/arc4-types.algo.ts:85 + // assert(b.equals(b2)) + == + assert + retsub + + // tests/approvals/arc4-types.algo.ts::testArrays(n: bytes) -> void: testArrays: // tests/approvals/arc4-types.algo.ts:68 @@ -75,10 +207,11 @@ testArrays: proto 1 0 // tests/approvals/arc4-types.algo.ts:69 // const myArray = new DynamicArray(n, n, n) + bytec_0 // 0x + frame_dig -1 + concat frame_dig -1 - dup concat - dup frame_dig -1 concat pushbytes 0x0003 @@ -87,8 +220,10 @@ testArrays: // tests/approvals/arc4-types.algo.ts:71 // myArray.push(n) extract 2 0 + bytec_0 // 0x frame_dig -1 concat + concat dup len intc_2 // 8 @@ -97,10 +232,23 @@ testArrays: extract 6 2 swap concat + // tests/approvals/arc4-types.algo.ts:73 + // const myStatic = new StaticArray(n, n) + bytec_0 // 0x + frame_dig -1 + concat + frame_dig -1 + concat + bytec_0 // 0x + swap + concat // tests/approvals/arc4-types.algo.ts:75 // assert(myStatic[0].equals(myArray.pop())) - swap - extract 0 8 // on error: Index access is out of bounds + intc_0 // 0 + intc_2 // 8 + * + intc_2 // 8 + extract3 // on error: Index access is out of bounds swap intc_2 // 8 callsub dynamic_array_pop_fixed_size @@ -115,17 +263,76 @@ testAddress: // tests/approvals/arc4-types.algo.ts:88 // function testAddress() { proto 0 0 - // tests/approvals/arc4-types.algo.ts:89 - // const a = new Address() - pushbytes base32(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) // addr AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ // tests/approvals/arc4-types.algo.ts:90 // const b = new Address(Txn.sender) txn Sender + // tests/approvals/arc4-types.algo.ts:89 + // const a = new Address() + bytec_2 // addr AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ // tests/approvals/arc4-types.algo.ts:92 // assert(!a.equals(b), 'Zero address should not match sender') == ! assert // Zero address should not match sender + // tests/approvals/arc4-types.algo.ts:89 + // const a = new Address() + bytec_2 // addr AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ + // tests/approvals/arc4-types.algo.ts:93 + // assert(a.equals(new Address()), 'Two zero addresses should match') + dup + == + assert // Two zero addresses should match + // tests/approvals/arc4-types.algo.ts:94 + // assert(a[0].equals(new Byte()), 'Zero address should start with zero byte') + intc_0 // 0 + intc_1 // 1 + * + // tests/approvals/arc4-types.algo.ts:89 + // const a = new Address() + bytec_2 // addr AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ + // tests/approvals/arc4-types.algo.ts:94 + // assert(a[0].equals(new Byte()), 'Zero address should start with zero byte') + swap + intc_1 // 1 + extract3 // on error: Index access is out of bounds + bytec_3 // 0x00 + == + assert // Zero address should start with zero byte + retsub + + +// tests/approvals/arc4-types.algo.ts::testTuple() -> void: +testTuple: + // tests/approvals/arc4-types.algo.ts:97 + // function testTuple() { + proto 0 0 + // tests/approvals/arc4-types.algo.ts:98 + // const t = new Tuple(new ARC4Uint64(34)) + bytec_0 // 0x + pushbytes 0x0000000000000022 + concat + // tests/approvals/arc4-types.algo.ts:99 + // const firstItem = t.at(0) + dup + intc_0 // 0 + intc_2 // 8 + extract3 // on error: Index access is out of bounds + swap + // tests/approvals/arc4-types.algo.ts:100 + // const firstItemIndexer = t.native[0] + intc_0 // 0 + intc_2 // 8 + extract3 // on error: Index access is out of bounds + // tests/approvals/arc4-types.algo.ts:101 + // assert(firstItem.equals(firstItemIndexer)) + == + assert + // tests/approvals/arc4-types.algo.ts:103 + // assert(t1.length === 2) + intc_3 // 2 + dup + == + assert retsub @@ -134,6 +341,23 @@ testDynamicBytes: // tests/approvals/arc4-types.algo.ts:48 // function testDynamicBytes(someBytes: bytes) { proto 1 0 + // tests/approvals/arc4-types.algo.ts:49 + // const db1 = new DynamicBytes() + bytec_1 // 0x0000 + // tests/approvals/arc4-types.algo.ts:50 + // assert(db1.native === Bytes(), 'No args should give empty bytes') + extract 2 0 + bytec_0 // 0x + == + assert // No args should give empty bytes + // tests/approvals/arc4-types.algo.ts:49 + // const db1 = new DynamicBytes() + bytec_1 // 0x0000 + // tests/approvals/arc4-types.algo.ts:51 + // assert(db1.bytes === new UintN<16>(0).bytes, 'bytes prop should return length header (of 0)') + dup + == + assert // bytes prop should return length header (of 0) // tests/approvals/arc4-types.algo.ts:52 // const db2 = new DynamicBytes(someBytes) frame_dig -1 @@ -148,6 +372,23 @@ testDynamicBytes: frame_dig -1 == assert + // tests/approvals/arc4-types.algo.ts:55 + // const db3 = new DynamicBytes('hello') + pushbytes 0x000568656c6c6f + // tests/approvals/arc4-types.algo.ts:56 + // assert(db3.native === Bytes('hello')) + extract 2 0 + pushbytes "hello" + == + assert + retsub + + +// tests/approvals/arc4-types.algo.ts::testStaticBytes() -> void: +testStaticBytes: + // tests/approvals/arc4-types.algo.ts:59 + // function testStaticBytes() { + proto 0 0 retsub @@ -155,9 +396,9 @@ testDynamicBytes: dynamic_array_pop_fixed_size: proto 2 2 frame_dig -2 - intc_3 // 0 + intc_0 // 0 extract_uint16 - intc_0 // 1 + intc_1 // 1 - itob extract 6 0 @@ -171,8 +412,9 @@ dynamic_array_pop_fixed_size: dup2 frame_dig -1 extract3 + cover 2 + swap + intc_0 // 0 uncover 2 - intc_3 // 0 - uncover 3 substring3 retsub diff --git a/tests/approvals/out/arc4-types/arc4-types.awst b/tests/approvals/out/arc4-types/arc4-types.awst index 003af230..94e78577 100644 --- a/tests/approvals/out/arc4-types/arc4-types.awst +++ b/tests/approvals/out/arc4-types/arc4-types.awst @@ -30,12 +30,12 @@ subroutine testStr(): void subroutine testDynamicBytes(someBytes: bytes): void { db1: arc4.dynamic_array = 0x0000 - assert(reinterpret_cast(db1)[2:] == 0x) + assert(ARC4_DECODE(db1) == 0x) assert(reinterpret_cast(db1) == reinterpret_cast(0)) db2: arc4.dynamic_array = ARC4_ENCODE(someBytes, wtype=arc4.dynamic_array) - assert(reinterpret_cast(db2)[2:] == someBytes) + assert(ARC4_DECODE(db2) == someBytes) db3: arc4.dynamic_array = 0x000568656c6c6f - assert(reinterpret_cast(db3)[2:] == "hello") + assert(ARC4_DECODE(db3) == "hello") } subroutine testStaticBytes(): void { @@ -84,6 +84,7 @@ contract Arc4TypesTestContract x: arc4.uint64 = 0 tests/approvals/arc4-types.algo.ts::testStr() tests/approvals/arc4-types.algo.ts::test(1, 2, 4) + tests/approvals/arc4-types.algo.ts::testUFixed() tests/approvals/arc4-types.algo.ts::testByte() tests/approvals/arc4-types.algo.ts::testArrays(65) tests/approvals/arc4-types.algo.ts::testAddress() diff --git a/tests/approvals/out/arc4-types/arc4-types.awst.json b/tests/approvals/out/arc4-types/arc4-types.awst.json index bb66895a..dc96d337 100644 --- a/tests/approvals/out/arc4-types/arc4-types.awst.json +++ b/tests/approvals/out/arc4-types/arc4-types.awst.json @@ -69,8 +69,8 @@ "file": "tests/approvals/arc4-types.algo.ts", "line": 17, "end_line": 17, - "column": 26, - "end_column": 33 + "column": 33, + "end_column": 40 }, "wtype": { "_type": "ARC4UFixedNxM", @@ -2309,7 +2309,7 @@ "scalar_type": 2 }, "lhs": { - "_type": "SliceExpression", + "_type": "ARC4Decode", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", "line": 50, @@ -2324,86 +2324,49 @@ "ephemeral": false, "scalar_type": 1 }, - "base": { - "_type": "ReinterpretCast", + "value": { + "_type": "VarExpression", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", "line": 50, "end_line": 50, "column": 9, - "end_column": 19 + "end_column": 12 }, "wtype": { - "_type": "WType", - "name": "bytes", + "_type": "ARC4DynamicArray", + "name": "arc4.dynamic_array", "immutable": true, "ephemeral": false, - "scalar_type": 1 - }, - "expr": { - "_type": "VarExpression", - "source_location": { - "file": "tests/approvals/arc4-types.algo.ts", - "line": 50, - "end_line": 50, - "column": 9, - "end_column": 12 + "scalar_type": 1, + "native_type": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 }, - "wtype": { - "_type": "ARC4DynamicArray", - "name": "arc4.dynamic_array", + "arc4_name": "byte[]", + "element_type": { + "_type": "ARC4UIntN", + "name": "arc4.byte", "immutable": true, "ephemeral": false, "scalar_type": 1, "native_type": { "_type": "WType", - "name": "bytes", - "immutable": true, - "ephemeral": false, - "scalar_type": 1 - }, - "arc4_name": "byte[]", - "element_type": { - "_type": "ARC4UIntN", - "name": "arc4.byte", + "name": "uint64", "immutable": true, "ephemeral": false, - "scalar_type": 1, - "native_type": { - "_type": "WType", - "name": "uint64", - "immutable": true, - "ephemeral": false, - "scalar_type": 2 - }, - "arc4_name": "byte", - "n": "8" + "scalar_type": 2 }, - "source_location": null + "arc4_name": "byte", + "n": "8" }, - "name": "db1" - } - }, - "begin_index": { - "_type": "IntegerConstant", - "source_location": { - "file": "tests/approvals/arc4-types.algo.ts", - "line": 50, - "end_line": 50, - "column": 9, - "end_column": 19 - }, - "wtype": { - "_type": "WType", - "name": "uint64", - "immutable": true, - "ephemeral": false, - "scalar_type": 2 + "source_location": null }, - "value": "2", - "teal_alias": null - }, - "end_index": null + "name": "db1" + } }, "operator": "==", "rhs": { @@ -2743,7 +2706,7 @@ "scalar_type": 2 }, "lhs": { - "_type": "SliceExpression", + "_type": "ARC4Decode", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", "line": 53, @@ -2758,86 +2721,49 @@ "ephemeral": false, "scalar_type": 1 }, - "base": { - "_type": "ReinterpretCast", + "value": { + "_type": "VarExpression", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", "line": 53, "end_line": 53, "column": 9, - "end_column": 19 + "end_column": 12 }, "wtype": { - "_type": "WType", - "name": "bytes", + "_type": "ARC4DynamicArray", + "name": "arc4.dynamic_array", "immutable": true, "ephemeral": false, - "scalar_type": 1 - }, - "expr": { - "_type": "VarExpression", - "source_location": { - "file": "tests/approvals/arc4-types.algo.ts", - "line": 53, - "end_line": 53, - "column": 9, - "end_column": 12 + "scalar_type": 1, + "native_type": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 }, - "wtype": { - "_type": "ARC4DynamicArray", - "name": "arc4.dynamic_array", + "arc4_name": "byte[]", + "element_type": { + "_type": "ARC4UIntN", + "name": "arc4.byte", "immutable": true, "ephemeral": false, "scalar_type": 1, "native_type": { "_type": "WType", - "name": "bytes", - "immutable": true, - "ephemeral": false, - "scalar_type": 1 - }, - "arc4_name": "byte[]", - "element_type": { - "_type": "ARC4UIntN", - "name": "arc4.byte", + "name": "uint64", "immutable": true, "ephemeral": false, - "scalar_type": 1, - "native_type": { - "_type": "WType", - "name": "uint64", - "immutable": true, - "ephemeral": false, - "scalar_type": 2 - }, - "arc4_name": "byte", - "n": "8" + "scalar_type": 2 }, - "source_location": null + "arc4_name": "byte", + "n": "8" }, - "name": "db2" - } - }, - "begin_index": { - "_type": "IntegerConstant", - "source_location": { - "file": "tests/approvals/arc4-types.algo.ts", - "line": 53, - "end_line": 53, - "column": 9, - "end_column": 19 - }, - "wtype": { - "_type": "WType", - "name": "uint64", - "immutable": true, - "ephemeral": false, - "scalar_type": 2 + "source_location": null }, - "value": "2", - "teal_alias": null - }, - "end_index": null + "name": "db2" + } }, "operator": "==", "rhs": { @@ -3005,7 +2931,7 @@ "scalar_type": 2 }, "lhs": { - "_type": "SliceExpression", + "_type": "ARC4Decode", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", "line": 56, @@ -3020,86 +2946,49 @@ "ephemeral": false, "scalar_type": 1 }, - "base": { - "_type": "ReinterpretCast", + "value": { + "_type": "VarExpression", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", "line": 56, "end_line": 56, "column": 9, - "end_column": 19 + "end_column": 12 }, "wtype": { - "_type": "WType", - "name": "bytes", + "_type": "ARC4DynamicArray", + "name": "arc4.dynamic_array", "immutable": true, "ephemeral": false, - "scalar_type": 1 - }, - "expr": { - "_type": "VarExpression", - "source_location": { - "file": "tests/approvals/arc4-types.algo.ts", - "line": 56, - "end_line": 56, - "column": 9, - "end_column": 12 + "scalar_type": 1, + "native_type": { + "_type": "WType", + "name": "bytes", + "immutable": true, + "ephemeral": false, + "scalar_type": 1 }, - "wtype": { - "_type": "ARC4DynamicArray", - "name": "arc4.dynamic_array", + "arc4_name": "byte[]", + "element_type": { + "_type": "ARC4UIntN", + "name": "arc4.byte", "immutable": true, "ephemeral": false, "scalar_type": 1, "native_type": { "_type": "WType", - "name": "bytes", - "immutable": true, - "ephemeral": false, - "scalar_type": 1 - }, - "arc4_name": "byte[]", - "element_type": { - "_type": "ARC4UIntN", - "name": "arc4.byte", + "name": "uint64", "immutable": true, "ephemeral": false, - "scalar_type": 1, - "native_type": { - "_type": "WType", - "name": "uint64", - "immutable": true, - "ephemeral": false, - "scalar_type": 2 - }, - "arc4_name": "byte", - "n": "8" + "scalar_type": 2 }, - "source_location": null + "arc4_name": "byte", + "n": "8" }, - "name": "db3" - } - }, - "begin_index": { - "_type": "IntegerConstant", - "source_location": { - "file": "tests/approvals/arc4-types.algo.ts", - "line": 56, - "end_line": 56, - "column": 9, - "end_column": 19 - }, - "wtype": { - "_type": "WType", - "name": "uint64", - "immutable": true, - "ephemeral": false, - "scalar_type": 2 + "source_location": null }, - "value": "2", - "teal_alias": null - }, - "end_index": null + "name": "db3" + } }, "operator": "==", "rhs": { @@ -3460,7 +3349,7 @@ "array_size": "5" }, "value": "s=LhH?f", - "encoding": "base16" + "encoding": "unknown" } } ], @@ -6618,7 +6507,7 @@ "source_location": { "file": "tests/approvals/arc4-types.algo.ts", "line": 111, - "end_line": 125, + "end_line": 126, "column": 36, "end_column": 3 }, @@ -6838,7 +6727,7 @@ "line": 115, "end_line": 115, "column": 4, - "end_column": 14 + "end_column": 16 }, "expr": { "_type": "SubroutineCallExpression", @@ -6847,7 +6736,7 @@ "line": 115, "end_line": 115, "column": 4, - "end_column": 14 + "end_column": 16 }, "wtype": { "_type": "WType", @@ -6858,7 +6747,7 @@ }, "target": { "_type": "SubroutineID", - "target": "tests/approvals/arc4-types.algo.ts::testByte" + "target": "tests/approvals/arc4-types.algo.ts::testUFixed" }, "args": [] } @@ -6870,7 +6759,7 @@ "line": 116, "end_line": 116, "column": 4, - "end_column": 33 + "end_column": 14 }, "expr": { "_type": "SubroutineCallExpression", @@ -6879,6 +6768,38 @@ "line": 116, "end_line": 116, "column": 4, + "end_column": 14 + }, + "wtype": { + "_type": "WType", + "name": "void", + "immutable": true, + "ephemeral": false, + "scalar_type": null + }, + "target": { + "_type": "SubroutineID", + "target": "tests/approvals/arc4-types.algo.ts::testByte" + }, + "args": [] + } + }, + { + "_type": "ExpressionStatement", + "source_location": { + "file": "tests/approvals/arc4-types.algo.ts", + "line": 117, + "end_line": 117, + "column": 4, + "end_column": 33 + }, + "expr": { + "_type": "SubroutineCallExpression", + "source_location": { + "file": "tests/approvals/arc4-types.algo.ts", + "line": 117, + "end_line": 117, + "column": 4, "end_column": 33 }, "wtype": { @@ -6900,8 +6821,8 @@ "_type": "IntegerConstant", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 116, - "end_line": 116, + "line": 117, + "end_line": 117, "column": 15, "end_column": 32 }, @@ -6932,8 +6853,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 117, - "end_line": 117, + "line": 118, + "end_line": 118, "column": 4, "end_column": 17 }, @@ -6941,8 +6862,8 @@ "_type": "SubroutineCallExpression", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 117, - "end_line": 117, + "line": 118, + "end_line": 118, "column": 4, "end_column": 17 }, @@ -6964,8 +6885,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 118, - "end_line": 118, + "line": 119, + "end_line": 119, "column": 4, "end_column": 15 }, @@ -6973,8 +6894,8 @@ "_type": "SubroutineCallExpression", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 118, - "end_line": 118, + "line": 119, + "end_line": 119, "column": 4, "end_column": 15 }, @@ -6996,8 +6917,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 119, - "end_line": 119, + "line": 120, + "end_line": 120, "column": 4, "end_column": 16 }, @@ -7005,8 +6926,8 @@ "_type": "SubroutineCallExpression", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 119, - "end_line": 119, + "line": 120, + "end_line": 120, "column": 4, "end_column": 16 }, @@ -7028,8 +6949,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 120, - "end_line": 120, + "line": 121, + "end_line": 121, "column": 4, "end_column": 41 }, @@ -7037,8 +6958,8 @@ "_type": "SubroutineCallExpression", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 120, - "end_line": 120, + "line": 121, + "end_line": 121, "column": 4, "end_column": 41 }, @@ -7061,8 +6982,8 @@ "_type": "BytesConstant", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 120, - "end_line": 120, + "line": 121, + "end_line": 121, "column": 27, "end_column": 39 }, @@ -7084,8 +7005,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 121, - "end_line": 121, + "line": 122, + "end_line": 122, "column": 4, "end_column": 21 }, @@ -7093,8 +7014,8 @@ "_type": "SubroutineCallExpression", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 121, - "end_line": 121, + "line": 122, + "end_line": 122, "column": 4, "end_column": 21 }, @@ -7116,8 +7037,8 @@ "_type": "AssignmentStatement", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 122, - "end_line": 122, + "line": 123, + "end_line": 123, "column": 10, "end_column": 58 }, @@ -7125,8 +7046,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 122, - "end_line": 122, + "line": 123, + "end_line": 123, "column": 10, "end_column": 16 }, @@ -7162,8 +7083,8 @@ "_type": "NewArray", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 122, - "end_line": 122, + "line": 123, + "end_line": 123, "column": 19, "end_column": 58 }, @@ -7193,8 +7114,8 @@ }, "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 122, - "end_line": 122, + "line": 123, + "end_line": 123, "column": 19, "end_column": 58 } @@ -7206,8 +7127,8 @@ "_type": "ExpressionStatement", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 123, - "end_line": 123, + "line": 124, + "end_line": 124, "column": 4, "end_column": 31 }, @@ -7215,8 +7136,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 123, - "end_line": 123, + "line": 124, + "end_line": 124, "column": 4, "end_column": 31 }, @@ -7234,8 +7155,8 @@ "_type": "NumericComparisonExpression", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 123, - "end_line": 123, + "line": 124, + "end_line": 124, "column": 11, "end_column": 30 }, @@ -7250,8 +7171,8 @@ "_type": "IntrinsicCall", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 123, - "end_line": 123, + "line": 124, + "end_line": 124, "column": 11, "end_column": 24 }, @@ -7269,8 +7190,8 @@ "_type": "VarExpression", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 123, - "end_line": 123, + "line": 124, + "end_line": 124, "column": 11, "end_column": 17 }, @@ -7306,8 +7227,8 @@ "_type": "IntegerConstant", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 123, - "end_line": 123, + "line": 124, + "end_line": 124, "column": 11, "end_column": 24 }, @@ -7329,8 +7250,8 @@ "_type": "IntegerConstant", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 123, - "end_line": 123, + "line": 124, + "end_line": 124, "column": 29, "end_column": 30 }, @@ -7353,8 +7274,8 @@ "_type": "ReturnStatement", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 124, - "end_line": 124, + "line": 125, + "end_line": 125, "column": 4, "end_column": 15 }, @@ -7362,8 +7283,8 @@ "_type": "BoolConstant", "source_location": { "file": "tests/approvals/arc4-types.algo.ts", - "line": 124, - "end_line": 124, + "line": 125, + "end_line": 125, "column": 11, "end_column": 15 }, diff --git a/tests/expected-output/arc4-types.algo.ts b/tests/expected-output/arc4-types.algo.ts index 4b39f5c6..ce51484a 100644 --- a/tests/expected-output/arc4-types.algo.ts +++ b/tests/expected-output/arc4-types.algo.ts @@ -14,7 +14,7 @@ import { } from '@algorandfoundation/algorand-typescript/arc4' function testUFixed() { - const a = new UFixedNxM('1.244', 32, 4) + const a = new UFixedNxM<32, 4>('1.244') const c = new UFixedNxM<32, 4>('1.244') assert(a.equals(c))