Skip to content

Commit

Permalink
fix: Update expected output tests and standardise transient type erro…
Browse files Browse the repository at this point in the history
…r messages
  • Loading branch information
tristanmenzel committed Oct 8, 2024
1 parent 1b27e8a commit 63f78fd
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 47 deletions.
4 changes: 2 additions & 2 deletions src/awst_build/eb/literal-expression-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import { InstanceBuilder } from './index'

export abstract class LiteralExpressionBuilder extends InstanceBuilder {
resolve(): Expression {
throw new CodeError('A literal value is not valid here', { sourceLocation: this.sourceLocation })
this.throwInvalidExpression()
}

resolveLValue(): LValue {
throw new CodeError('A literal value is not valid here', { sourceLocation: this.sourceLocation })
throw new CodeError('A literal value is not a valid assignment target', { sourceLocation: this.sourceLocation })
}

abstract resolvableToPType(ptype: PTypeOrClass): boolean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { nodeFactory } from '../../../awst/node-factory'
import type { Expression, LValue } from '../../../awst/nodes'
import type { Expression } from '../../../awst/nodes'
import type { SourceLocation } from '../../../awst/source-location'
import { CodeError } from '../../../errors'
import { codeInvariant } from '../../../util'
Expand All @@ -23,13 +23,6 @@ import { UInt64ExpressionBuilder } from '../uint64-expression-builder'
import { isValidLiteralForPType } from '../util'

export class BigIntLiteralExpressionBuilder extends LiteralExpressionBuilder {
resolve(): Expression {
throw new CodeError(this.ptype.expressionMessage, { sourceLocation: this.sourceLocation })
}
resolveLValue(): LValue {
throw new CodeError('A literal value is not a valid assignment target', { sourceLocation: this.sourceLocation })
}

singleEvaluation(): InstanceBuilder {
return this
}
Expand Down
66 changes: 36 additions & 30 deletions src/awst_build/ptypes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Constants } from '../../constants'
import { CodeError, InternalError, NotSupported } from '../../errors'
import { codeInvariant, distinct, sortBy } from '../../util'
import { PType } from './base'
import { transientTypeErrors } from './transient-type-errors'

export * from './base'
export * from './intrinsic-enum-type'
Expand All @@ -14,7 +15,7 @@ export * from './op-ptypes'
/**
* Transient types can appear in expressions but should not be used as variable or return types
*/
export class TransientType extends PType {
export abstract class TransientType extends PType {
readonly name: string
readonly module: string
readonly singleton: boolean
Expand Down Expand Up @@ -135,21 +136,26 @@ export class UnionPType extends TransientType {
private constructor({ types }: { types: PType[] }) {
let typeMessage: string
let expressionMessage: string
const name = types.map((t) => t.name).join(' | ')
const transientType = types.find((t) => t instanceof TransientType)
if (transientType) {
typeMessage = transientType.typeMessage
expressionMessage = transientType.expressionMessage
if (transientType instanceof NativeNumericType) {
typeMessage = transientTypeErrors.nativeNumeric(name).usedAsType
expressionMessage = transientTypeErrors.nativeNumeric(name).usedInExpression
} else {
typeMessage = transientType.typeMessage
expressionMessage = transientType.expressionMessage
}
} else {
typeMessage = 'Union types are not valid as a variable, parameter, return, or property type.'
expressionMessage = 'Union types are only valid in boolean expressions.'
typeMessage = transientTypeErrors.unionTypes(name).usedAsType
expressionMessage = transientTypeErrors.unionTypes(name).usedInExpression
}
const name = types.map((t) => t.name).join(' | ')
super({
name,
module: 'lib.d.ts',
singleton: false,
typeMessage: `${typeMessage} Expression type is ${name}`,
expressionMessage: `${expressionMessage} Expression type is ${name}`,
typeMessage,
expressionMessage,
})
this.types = types
}
Expand Down Expand Up @@ -440,13 +446,13 @@ export class ArrayLiteralPType extends TransientType {
readonly items: PType[]
readonly immutable = true
constructor(props: { items: PType[] }) {
const name = `[${props.items.map((i) => i.name).join(', ')}]`
super({
module: 'lib.d.ts',
name: `[${props.items.map((i) => i.name).join(', ')}]`,
typeMessage:
'Native array types are not valid as variable, parameter, return, or property types. Please define a static tuple type or use an `as const` expression',
name,
typeMessage: transientTypeErrors.arrays(name).usedAsType,
expressionMessage: transientTypeErrors.arrays(name).usedInExpression,
singleton: false,
expressionMessage: '',
})
this.items = props.items
}
Expand Down Expand Up @@ -504,11 +510,11 @@ export class ArrayPType extends TransientType {
return `${this.module}::Array<${this.itemType.fullName}>`
}
constructor(props: { itemType: PType; immutable: boolean }) {
const name = `Array<${props.itemType.name}>`
super({
name: `Array<${props.itemType.name}>`,
typeMessage:
'Native array types are not valid as variable, parameter, return, or property types. Please define a static tuple type or use an `as const` expression',
expressionMessage: '',
name,
typeMessage: transientTypeErrors.arrays(name).usedAsType,
expressionMessage: transientTypeErrors.arrays(name).usedInExpression,
module: 'lib.d.ts',
singleton: false,
})
Expand Down Expand Up @@ -633,14 +639,14 @@ export const BooleanFunction = new LibFunctionType({
module: 'typescript/lib/lib.es5.d.ts',
})

export const bigIntPType = new TransientType({
export class NativeNumericType extends TransientType {}

export const bigIntPType = new NativeNumericType({
name: 'bigint',
module: 'lib.d.ts',
singleton: false,
typeMessage:
'`bigint` is not valid as a variable, parameter, return, or property type. Please use an algo-ts type such as `biguint` or `uint64`',
expressionMessage:
'Expression of type `bigint` must be explicitly converted to an algo-ts type, for example by wrapping the expression in `BigUint(...)`',
typeMessage: transientTypeErrors.nativeNumeric('bigint').usedAsType,
expressionMessage: transientTypeErrors.nativeNumeric('bigint').usedInExpression,
})
export const stringPType = new InstanceType({
name: 'string',
Expand All @@ -662,38 +668,38 @@ export const biguintPType = new InstanceType({
module: Constants.primitivesModuleName,
wtype: wtypes.biguintWType,
})
export class NumericLiteralPType extends TransientType {
export class NumericLiteralPType extends NativeNumericType {
readonly literalValue: bigint
constructor({ literalValue }: { literalValue: bigint }) {
super({
name: `${literalValue}`,
module: 'lib.d.ts',
singleton: false,
typeMessage: `\`${literalValue}\` is not valid as a variable, parameter, return, or property type. Please use an algo-ts type such as \`uint64\` or \`biguint\``,
expressionMessage: `Expression of type \`${literalValue}\` must be explicitly converted to an algo-ts type, for example by wrapping the expression in \`Uint64(...)\``,
typeMessage: transientTypeErrors.nativeNumeric(literalValue.toString()).usedAsType,
expressionMessage: transientTypeErrors.nativeNumeric(literalValue.toString()).usedInExpression,
})
this.literalValue = literalValue
}
}
export class BigIntLiteralPType extends TransientType {
export class BigIntLiteralPType extends NativeNumericType {
readonly literalValue: bigint
constructor({ literalValue }: { literalValue: bigint }) {
super({
name: `${literalValue}n`,
module: 'lib.d.ts',
singleton: false,
typeMessage: `\`${literalValue}n\` is not valid as a variable, parameter, return, or property type. Please use an algo-ts type such as \`uint64\` or \`biguint\``,
expressionMessage: `Expression of type \`${literalValue}n\` must be explicitly converted to an algo-ts type, for example by wrapping the expression in \`BigUint(...)\``,
typeMessage: transientTypeErrors.nativeNumeric(`${literalValue}n`).usedAsType,
expressionMessage: transientTypeErrors.nativeNumeric(`${literalValue}n`).usedInExpression,
})
this.literalValue = literalValue
}
}
export const numberPType = new TransientType({
export const numberPType = new NativeNumericType({
name: 'number',
module: 'lib.d.ts',
singleton: false,
typeMessage: `\`number\` is not valid as a variable, parameter, return, or property type. Please use an algo-ts type such as \`uint64\` or \`biguint\``,
expressionMessage: `Expression of type \`number\` must be explicitly converted to an algo-ts type, for example by wrapping the expression in \`Uint64(...)\``,
typeMessage: transientTypeErrors.nativeNumeric('number').usedAsType,
expressionMessage: transientTypeErrors.nativeNumeric('number').usedInExpression,
})
export const Uint64Function = new LibFunctionType({
name: 'Uint64',
Expand Down
19 changes: 19 additions & 0 deletions src/awst_build/ptypes/transient-type-errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
type TransientTypeError = {
usedAsType: string
usedInExpression: string
}

export const transientTypeErrors = {
arrays: (typeName) => ({
usedAsType: `\`${typeName}\` is not valid as a variable, parameter, return, or property type. Please define a static tuple type or use an \`as const\` expression`,
usedInExpression: `Expression of type \`${typeName}\` cannot be used conditionally`,
}),
nativeNumeric: (typeName) => ({
usedAsType: `\`${typeName}\` is not valid as a variable, parameter, return, or property type. Please use an algo-ts type such as \`biguint\` or \`uint64\``,
usedInExpression: `Expression of type \`${typeName}\` must be explicitly converted to an algo-ts type, for example by wrapping the expression in \`Uint64(...)\` or \`BigUint(...)\``,
}),
unionTypes: (typeName) => ({
usedAsType: `Union types are not valid as a variable, parameter, return, or property type. Expression type is ${typeName}`,
usedInExpression: `Union types are only valid in boolean expressions. Expression type is ${typeName}`,
}),
} satisfies Record<string, (typeName: string) => TransientTypeError>
6 changes: 3 additions & 3 deletions tests/expected-output/array-literals.algo.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import type { uint64 } from '@algorandfoundation/algorand-typescript'

function test(a: uint64, b: uint64) {
// @expect-error Native array types are not valid...
// @expect-error `Array<uint64>` is not valid as a variable, parameter, return, or property type...
const inferArray = [a, b]

const inferTuple = [a, b] as const

const explicitTuple: [uint64, uint64] = [a, b]

// @expect-error Native array types are not valid...
// @expect-error `Array<uint64>` is not valid as a variable, parameter, return, or property type...
const conditionalInferArray = a < b ? [a, b] : [b, a]
const conditionalExplicitTuple: [uint64, uint64] = a < b ? [a, b] : [b, a]

const [c, d] = [a, b]

// @expect-error Spread operator is not supported in assignment expressions where the resulting type is a variadic array
// @expect-error `Array<uint64>` is not valid as a variable, parameter, return, or property type...
const [...e] = [a, b]
// @expect-error Spread operator is not currently supported with tuple expressions
const [...f] = [a, b] as const
Expand Down
4 changes: 2 additions & 2 deletions tests/expected-output/conditional-expression.algo.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { uint64 } from '@algorandfoundation/algorand-typescript'

function test(x: uint64, y: uint64) {
// @expect-error Expression of type `number` must be explicitly converted to an algo-ts type...
// @expect-error Expression of type `1 | 2` must be explicitly converted to an algo-ts type...
const d: uint64 = (y % 2 ? 2 : 1) + (x < 4 ? x : y)
// @expect-error Expression of type `number` must be explicitly converted to an algo-ts type...
// @expect-error Expression of type `1 | 2` must be explicitly converted to an algo-ts type...
const f = (y % 2 ? 2 : 1) === (x < 4 ? x : y)
}
2 changes: 1 addition & 1 deletion tests/expected-output/invalid-array-usage.algo.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Uint64 } from '@algorandfoundation/algorand-typescript'

function test() {
// @expect-error Native array types are not valid as variable, parameter, return, or property types...
// @expect-error `Array<uint64>` is not valid as a variable, parameter, return, or property type. Please define a static tuple type or use an `as const` expression
const myArray = [Uint64(1), Uint64(2)]
}
2 changes: 1 addition & 1 deletion tests/expected-output/numeric-literal-expressions.algo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { biguint } from '@algorandfoundation/algorand-typescript'

function test_uint64() {
// @expect-error `number` is not valid as a variable, parameter, return, or property type. Please use an algo-ts type such as `uint64` or `biguint`
// @expect-error `number` is not valid as a variable, parameter, return, or property type. Please use an algo-ts type such as `biguint` or `uint64`
const x = 4 * 100 + 10
}

Expand Down

0 comments on commit 63f78fd

Please sign in to comment.