Skip to content

Commit

Permalink
refactor: simplify type info passed to fromBytes and fromLog method
Browse files Browse the repository at this point in the history
  • Loading branch information
boblat committed Nov 26, 2024
1 parent 72dc26a commit 66167f4
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 12 deletions.
78 changes: 75 additions & 3 deletions packages/algo-ts/src/arc4/encoded-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ export class UintN<N extends BitSize> extends ARC4Encoded {
get native(): NativeForArc4Int<N> {
throw new Error('TODO')
}

static fromBytes<N extends BitSize, I = UintN<N>>(this: { new (...args: DeliberateAny): I }, bytes: BytesCompat): I {
throw new Error('todo')
}

static fromLog<N extends BitSize, I = UintN<N>>(this: { new (...args: DeliberateAny): I }, log: BytesCompat): I {
throw new Error('todo')
}
}
export class UFixedNxM<N extends BitSize, M extends number> extends ARC4Encoded {
__type?: `arc4.UFixedNxM<${N}x${M}>`
Expand All @@ -58,12 +66,30 @@ export class UFixedNxM<N extends BitSize, M extends number> extends ARC4Encoded
get native(): NativeForArc4Int<N> {
throw new Error('TODO')
}
}

static fromBytes<N extends BitSize, M extends number, I = UFixedNxM<N, M>>(
this: { new (...args: DeliberateAny): I },
bytes: BytesCompat,
): I {
throw new Error('todo')
}

static fromLog<N extends BitSize, M extends number, I = UFixedNxM<N, M>>(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<I = Byte>(this: { new (...args: DeliberateAny): I }, bytes: BytesCompat): I {
throw new Error('todo')
}

static fromLog<I = Byte>(this: { new (...args: DeliberateAny): I }, log: BytesCompat): I {
throw new Error('todo')
}
}
export class Bool extends ARC4Encoded {
__type?: `arc4.Bool`
Expand Down Expand Up @@ -187,8 +213,21 @@ export class StaticArray<TItem extends ARC4Encoded, TLength extends number> exte
copy(): StaticArray<TItem, TLength> {
return new StaticArray<TItem, TLength>(...this.items)
}
}

static fromBytes<TItem extends ARC4Encoded, TLength extends number, I = StaticArray<TItem, TLength>>(
this: { new (...args: DeliberateAny): I },
bytes: BytesCompat,
): I {
throw new Error('todo')
}

static fromLog<TItem extends ARC4Encoded, TLength extends number, I = StaticArray<TItem, TLength>>(
this: { new (...args: DeliberateAny): I },
log: BytesCompat,
): I {
throw new Error('todo')
}
}
export class DynamicArray<TItem extends ARC4Encoded> extends Arc4ReadonlyArray<TItem> {
__type?: `arc4.DynamicArray<${TItem['__type']}>`
constructor(...items: TItem[]) {
Expand All @@ -215,6 +254,14 @@ export class DynamicArray<TItem extends ARC4Encoded> extends Arc4ReadonlyArray<T
copy(): DynamicArray<TItem> {
return new DynamicArray<TItem>(...this.items)
}

static fromBytes<TItem extends ARC4Encoded, I = DynamicArray<TItem>>(this: { new (...args: DeliberateAny): I }, bytes: BytesCompat): I {
throw new Error('todo')
}

static fromLog<TItem extends ARC4Encoded, I = DynamicArray<TItem>>(this: { new (...args: DeliberateAny): I }, log: BytesCompat): I {
throw new Error('todo')
}
}
type ExpandTupleType<T extends ARC4Encoded[]> = T extends [infer T1 extends ARC4Encoded, ...infer TRest extends ARC4Encoded[]]
? TRest extends []
Expand All @@ -241,6 +288,20 @@ export class Tuple<TTuple extends [ARC4Encoded, ...ARC4Encoded[]]> extends ARC4E
get native(): TTuple {
return this.#items
}

static fromBytes<TTuple extends [ARC4Encoded, ...ARC4Encoded[]], I = Tuple<TTuple>>(
this: { new (...args: TTuple): I },
bytes: BytesCompat,
): I {
throw new Error('todo')
}

static fromLog<TTuple extends [ARC4Encoded, ...ARC4Encoded[]], I = Tuple<TTuple>>(
this: { new (...args: TTuple): I },
log: BytesCompat,
): I {
throw new Error('todo')
}
}

export class Address extends Arc4ReadonlyArray<Byte> {
Expand Down Expand Up @@ -282,8 +343,19 @@ class StructImpl<T extends StructConstraint> extends StructBase {
})
}
}
static fromBytes<T extends StructConstraint, I = StructBase & T>(this: { new (args: T): I }, bytes: BytesCompat): I {
throw new Error('todo')
}

static fromLog<T extends StructConstraint, I = StructBase & T>(this: { new (args: T): I }, log: BytesCompat): I {
throw new Error('todo')
}
}

type StructConstructor = new <T extends StructConstraint>(initial: T) => StructBase & T
type StructConstructor = {
new <T extends StructConstraint>(initial: T): StructBase & T
fromBytes: <T extends StructConstraint>(bytes: BytesCompat) => StructBase & T
fromLog: <T extends StructConstraint>(log: BytesCompat) => StructBase & T
}

export const Struct = StructImpl as StructConstructor
49 changes: 42 additions & 7 deletions src/awst_build/eb/arc4/base.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { nodeFactory } from '../../../awst/node-factory'
import type { Expression } from '../../../awst/nodes'
import { EqualityComparison } from '../../../awst/nodes'
import { BytesConstant, EqualityComparison } from '../../../awst/nodes'
import type { SourceLocation } from '../../../awst/source-location'
import { wtypes } from '../../../awst/wtypes'
import { CodeError } from '../../../errors'
Expand Down Expand Up @@ -103,40 +103,70 @@ 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<NodeBuilder>, typeArgs: ReadonlyArray<PType>, sourceLocation: SourceLocation): NodeBuilder {
const funcName = 'fromBytes'
const {
ptypes: [ptype],
ptypes,
args: [initialValueBuilder],
} = parseFunctionArgs({
args,
typeArgs,
genericTypeArgs: 1,
genericTypeArgs: this.genericArgsCount ?? 1,
funcName,
argSpec: (a) => [a.required(bytesPType)],
callLocation: sourceLocation,
})

const ptype = (this.ptypeFactory ? this.ptypeFactory(ptypes) : ptypes[0]) as ARC4EncodedType
const initialValue = initialValueBuilder.resolveToPType(bytesPType).resolve()
return typeRegistry.getInstanceEb(initialValue, ptype)
const initialValueExpr =
initialValue instanceof BytesConstant
? nodeFactory.bytesConstant({
value: initialValue.value,
wtype: ptype.wtypeOrThrow,
sourceLocation: sourceLocation,
})
: 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<NodeBuilder>, typeArgs: ReadonlyArray<PType>, sourceLocation: SourceLocation): NodeBuilder {
const funcName = 'fromLog'
const {
ptypes: [ptype],
ptypes,
args: [initialValueBuilder],
} = parseFunctionArgs({
args,
typeArgs,
genericTypeArgs: 1,
genericTypeArgs: this.genericArgsCount ?? 1,
funcName,
argSpec: (a) => [a.required(bytesPType)],
callLocation: sourceLocation,
})

const ptype = (this.ptypeFactory ? this.ptypeFactory(ptypes) : ptypes[0]) as ARC4EncodedType
const initialValue = initialValueBuilder.resolveToPType(bytesPType).resolve()
const arc4Value = nodeFactory.intrinsicCall({
opCode: 'extract',
Expand All @@ -145,6 +175,11 @@ export class Arc4EncodedFromLogFunctionBuilder extends FunctionBuilder {
stackArgs: [initialValue],
sourceLocation,
})
const arc4ValueExpr = nodeFactory.reinterpretCast({
wtype: ptype.wtype,
sourceLocation,
expr: arc4Value,
})
const arc4Prefix = nodeFactory.intrinsicCall({
opCode: 'extract',
immediates: [0n, 4n],
Expand All @@ -160,7 +195,7 @@ export class Arc4EncodedFromLogFunctionBuilder extends FunctionBuilder {
})

const fromLogExpr = nodeFactory.checkedMaybe({
expr: nodeFactory.tupleExpression({ items: [arc4Value, arc4PrefixIsValid], sourceLocation }),
expr: nodeFactory.tupleExpression({ items: [arc4ValueExpr, arc4PrefixIsValid], sourceLocation }),
comment: 'ARC4 prefix is valid',
})
return typeRegistry.getInstanceEb(fromLogExpr, ptype)
Expand Down
19 changes: 18 additions & 1 deletion src/awst_build/eb/arc4/ufixed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import { UFixedNxMClass, UFixedNxMType } from '../../ptypes/arc4-types'
import { type InstanceBuilder, type NodeBuilder } from '../index'
import { isValidLiteralForPType, requireStringConstant } from '../util'
import { parseFunctionArgs } from '../util/arg-parsing'
import { Arc4EncodedBaseClassBuilder, Arc4EncodedBaseExpressionBuilder } from './base'
import {
Arc4EncodedBaseClassBuilder,
Arc4EncodedBaseExpressionBuilder,
Arc4EncodedFromBytesFunctionBuilder,
Arc4EncodedFromLogFunctionBuilder,
} from './base'

export class UFixedNxMClassBuilder extends Arc4EncodedBaseClassBuilder {
readonly ptype = UFixedNxMClass
Expand Down Expand Up @@ -40,6 +45,18 @@ export class UFixedNxMClassBuilder extends Arc4EncodedBaseClassBuilder {

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) {
Expand Down
18 changes: 17 additions & 1 deletion src/awst_build/eb/arc4/uintn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import { arc4ByteAlias, ByteClass, UintNClass, UintNType } from '../../ptypes/ar
import type { InstanceBuilder, NodeBuilder } from '../index'
import { isValidLiteralForPType } from '../util'
import { parseFunctionArgs } from '../util/arg-parsing'
import { Arc4EncodedBaseClassBuilder, Arc4EncodedBaseExpressionBuilder } from './base'
import {
Arc4EncodedBaseClassBuilder,
Arc4EncodedBaseExpressionBuilder,
Arc4EncodedFromBytesFunctionBuilder,
Arc4EncodedFromLogFunctionBuilder,
} from './base'

export class UintNClassBuilder extends Arc4EncodedBaseClassBuilder {
readonly ptype = UintNClass
Expand All @@ -36,6 +41,17 @@ export class UintNClassBuilder extends Arc4EncodedBaseClassBuilder {

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 Arc4EncodedBaseClassBuilder {
Expand Down

0 comments on commit 66167f4

Please sign in to comment.