Skip to content

Commit

Permalink
feat: Native arrays and MutableArray type (#106)
Browse files Browse the repository at this point in the history
fix: Missing implementation for GlobalState.delete
  • Loading branch information
tristanmenzel authored Feb 19, 2025
1 parent e7e7fd5 commit e04b710
Show file tree
Hide file tree
Showing 1,892 changed files with 105,990 additions and 335,092 deletions.
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"scripts": {
"postinstall": "npx patch-package",
"dev:examples": "tsx src/cli.ts build examples --output-awst --output-awst-json",
"dev:approvals": "rimraf tests/approvals/out && tsx src/cli.ts build tests/approvals --dry-run",
"dev:approvals": "tsx src/cli.ts build tests/approvals --dry-run",
"dev:expected-output": "tsx src/cli.ts build tests/expected-output --dry-run",
"dev:testing": "tsx src/cli.ts build tests/approvals/switch-statements.algo.ts --output-awst --output-awst-json --output-ssa-ir --log-level=info --out-dir out/unoptimized/[name] --optimization-level=1",
"dev:testing": "tsx src/cli.ts build tests/approvals/native-arrays.algo.ts tests/approvals/mutable-arrays.algo.ts --output-awst --output-awst-json --output-ssa-ir --log-level=info --out-dir out/unoptimized/[name] --optimization-level=1",
"audit": "better-npm-audit audit",
"format": "prettier --write .",
"lint": "eslint \"src/**/*.ts\"",
Expand Down Expand Up @@ -38,7 +38,7 @@
"author": "Algorand foundation",
"license": "MIT",
"devDependencies": {
"@algorandfoundation/algokit-utils": "^8.0.2",
"@algorandfoundation/algokit-utils": "^8.1.0",
"@algorandfoundation/algorand-typescript": "file:packages/algo-ts/dist",
"@commitlint/cli": "^19.6.0",
"@commitlint/config-conventional": "^19.6.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/algo-ts/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/algo-ts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@algorandfoundation/algorand-typescript",
"version": "1.0.0-beta.17",
"version": "1.0.0-beta.18",
"description": "This package contains definitions for the types which comprise Algorand TypeScript which can be compiled to run on the Algorand Virtual Machine using the Puya compiler.",
"private": false,
"main": "index.js",
Expand Down
32 changes: 32 additions & 0 deletions packages/algo-ts/src/arc4/encoded-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,14 @@ export class StaticArray<TItem extends ARC4Encoded, TLength extends number> exte
copy(): StaticArray<TItem, TLength> {
throw new NoImplementation()
}

/**
* Returns a new array containing all items from _this_ array, and _other_ array
* @param other Another array to concat with this one
*/
concat(other: Arc4ReadonlyArray<TItem>): DynamicArray<TItem> {
throw new NoImplementation()
}
}
export class DynamicArray<TItem extends ARC4Encoded> extends Arc4ReadonlyArray<TItem> {
[TypeProperty]?: `arc4.DynamicArray<${TItem[typeof TypeProperty]}>`
Expand All @@ -230,6 +238,14 @@ export class DynamicArray<TItem extends ARC4Encoded> extends Arc4ReadonlyArray<T
copy(): DynamicArray<TItem> {
throw new NoImplementation()
}

/**
* Returns a new array containing all items from _this_ array, and _other_ array
* @param other Another array to concat with this one
*/
concat(other: Arc4ReadonlyArray<TItem>): DynamicArray<TItem> {
throw new NoImplementation()
}
}
type ExpandTupleType<T extends ARC4Encoded[]> = T extends [infer T1 extends ARC4Encoded, ...infer TRest extends ARC4Encoded[]]
? TRest extends []
Expand Down Expand Up @@ -299,6 +315,14 @@ export class DynamicBytes extends Arc4ReadonlyArray<Byte> {
get native(): bytes {
throw new NoImplementation()
}

/**
* Returns a dynamic bytes object containing all bytes from _this_ and _other_
* @param other Another array of bytes to concat with this one
*/
concat(other: Arc4ReadonlyArray<Byte>): DynamicBytes {
throw new NoImplementation()
}
}

export class StaticBytes<TLength extends number = 0> extends Arc4ReadonlyArray<Byte> {
Expand All @@ -311,6 +335,14 @@ export class StaticBytes<TLength extends number = 0> extends Arc4ReadonlyArray<B
get native(): bytes {
throw new NoImplementation()
}

/**
* Returns a dynamic bytes object containing all bytes from _this_ and _other_
* @param other Another array of bytes to concat with this one
*/
concat(other: Arc4ReadonlyArray<Byte>): DynamicBytes {
throw new NoImplementation()
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/algo-ts/src/itxn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface ApplicationInnerTxn extends txnTypes.ApplicationTxn {
[isItxn]?: true
}

type AccountInput = Account | bytes | string
type AccountInput = Account | bytes
type AssetInput = Asset | uint64
type ApplicationInput = Application | uint64

Expand Down
10 changes: 10 additions & 0 deletions packages/algo-ts/src/logic-sig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export abstract class LogicSig {
abstract program(): boolean | uint64
}

type NumberRange = { from: number; to: number }

/**
* Defines optional configuration for a logic signature
*/
Expand All @@ -19,6 +21,14 @@ type LogicSigOptions = {
* Defaults to the class name
*/
name?: string
/**
* Allows you to mark a slot ID or range of slot IDs as "off limits" to Puya.
* These slot ID(s) will never be written to or otherwise manipulating by the compiler itself.
* This is particularly useful in combination with `op.gload_bytes` / `op.gload_uint64`
* which lets a contract in a group transaction read from the scratch slots of another contract
* that occurs earlier in the transaction group.
*/
scratchSlots?: Array<number | NumberRange>
}

/**
Expand Down
3 changes: 3 additions & 0 deletions packages/algo-ts/src/mutable-array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,22 @@ export class MutableArray<TItem> {

/**
* Create a new Dynamic array with all items from this array
* @internal Not supported yet
*/
slice(): MutableArray<TItem>
/**
* Create a new MutableArray with all items up till `end`.
* Negative indexes are taken from the end.
* @param end An index in which to stop copying items.
* @internal Not supported yet
*/
slice(end: Uint64Compat): MutableArray<TItem>
/**
* Create a new MutableArray with items from `start`, up until `end`
* Negative indexes are taken from the end.
* @param start An index in which to start copying items.
* @param end An index in which to stop copying items
* @internal Not supported yet
*/
slice(start: Uint64Compat, end: Uint64Compat): MutableArray<TItem>
slice(start?: Uint64Compat, end?: Uint64Compat): MutableArray<TItem> {
Expand Down
5 changes: 4 additions & 1 deletion packages/algo-ts/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
"extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": {
"noEmit": true,
"target": "ES2022",
"lib": [
"ES2023"
],
"target": "ES2023",
"module": "ESNext",
"moduleResolution": "Bundler",
"resolveJsonModule": true,
Expand Down
20 changes: 1 addition & 19 deletions src/awst/json-serialize-awst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import { snakeCase } from 'change-case'
import path from 'node:path'
import { Constants } from '../constants'
import { InternalError } from '../errors'
import { logger } from '../logger'
import { invariant } from '../util'
import { buildBase85Encoder } from '../util/base-85'
import { ARC4ABIMethodConfig, ContractReference, LogicSigReference } from './models'
import { ContractReference, LogicSigReference } from './models'
import type { RootNode } from './nodes'
import { IntrinsicCall, SingleEvaluation } from './nodes'
import { SourceLocation } from './source-location'
Expand Down Expand Up @@ -112,23 +111,6 @@ export class AwstSerializer extends SnakeCaseSerializer<RootNode[]> {
id: String(this.#singleEvals.forSymbol(value.id)[0]),
}
}
if (value instanceof ARC4ABIMethodConfig) {
// TODO: This can be removed once puya has been updated to support a more advanced default args schema
return {
_type: value.constructor.name,
...(super.serializerFunction(key, value) as object),
default_args: Object.fromEntries(
Object.entries(value.defaultArgs).flatMap(([key, v]) => {
if (v.source === 'constant') {
logger.warn(value.sourceLocation, `Ignoring constant default value for ${key} as puya does not support this yet`)
return []
} else {
return [[key, v.memberName]]
}
}),
),
}
}
if (value instanceof Uint8Array) {
return this.b85.encode(value)
}
Expand Down
65 changes: 0 additions & 65 deletions src/awst/models.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import type { ContractClassPType, LogicSigPType } from '../awst_build/ptypes'
import type { Props } from '../typescript-helpers'
import type { SourceLocation } from './source-location'

export enum OnCompletionAction {
NoOp = 0,
Expand All @@ -11,12 +9,6 @@ export enum OnCompletionAction {
DeleteApplication = 5,
}

export enum ARC4CreateOption {
Allow = 1,
Require = 2,
Disallow = 3,
}

class ModelBase {
/**
* This field prevents us from accidentally passing an object literal with structural equality to
Expand All @@ -26,63 +18,6 @@ class ModelBase {
#isModel = true
}

export class ARC4BareMethodConfig extends ModelBase {
readonly sourceLocation: SourceLocation | undefined
readonly allowedCompletionTypes: OnCompletionAction[]
readonly create: ARC4CreateOption
readonly isBare = true
constructor(props: Omit<Props<ARC4BareMethodConfig>, 'isBare'>) {
super()
this.sourceLocation = props.sourceLocation
this.allowedCompletionTypes = props.allowedCompletionTypes
this.create = props.create
}
}

export type DefaultArgumentSource =
| {
source: 'constant'
value: string | bigint | number | boolean | Uint8Array
}
| {
source: 'global-state'
memberName: string
}
| {
source: 'local-state'
memberName: string
}
| {
source: 'abi-method'
memberName: string
}

export class ARC4ABIMethodConfig extends ModelBase {
readonly sourceLocation: SourceLocation | undefined
readonly name: string
readonly isBare = false
readonly create: ARC4CreateOption
readonly readonly: boolean
readonly allowedCompletionTypes: OnCompletionAction[]
readonly defaultArgs: Record<string, DefaultArgumentSource>
readonly structs: Record<string, ARC32StructDef>
constructor(props: Omit<Props<ARC4ABIMethodConfig>, 'isBare'>) {
super()
this.sourceLocation = props.sourceLocation
this.name = props.name
this.create = props.create
this.readonly = props.readonly
this.allowedCompletionTypes = props.allowedCompletionTypes
this.defaultArgs = props.defaultArgs
this.structs = props.structs
}
}

export interface ARC32StructDef {
name: string
elements: [...[string, string][]]
}

export class ContractReference extends ModelBase {
constructor({ className, moduleName }: { className: string; moduleName: string }) {
super()
Expand Down
29 changes: 29 additions & 0 deletions src/awst/node-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import type { DeliberateAny, Props } from '../typescript-helpers'
import { codeInvariant, instanceOfAny, invariant } from '../util'
import type { Expression, Statement } from './nodes'
import {
ArrayLength,
ArrayReplace,
AssignmentExpression,
AssignmentStatement,
BigUIntBinaryOperation,
Expand Down Expand Up @@ -254,6 +256,33 @@ const explicitNodeFactory = {
sourceLocation,
})
},
arrayLength({ array, sourceLocation }: { array: Expression; sourceLocation: SourceLocation }) {
return new ArrayLength({
array,
sourceLocation,
wtype: wtypes.uint64WType,
})
},
arrayReplace({
base,
index,
value,
sourceLocation,
}: {
base: Expression
index: Expression
value: Expression
sourceLocation: SourceLocation
}) {
invariant(base.wtype instanceof wtypes.StackArray, 'base must have wtype of StackArray', base.sourceLocation)
return new ArrayReplace({
base,
index,
value,
sourceLocation,
wtype: base.wtype,
})
},
} satisfies { [key in keyof ConcreteNodes]?: (...args: DeliberateAny[]) => DeliberateAny }

type ExplicitNodeFactory = typeof explicitNodeFactory
Expand Down
Loading

0 comments on commit e04b710

Please sign in to comment.