Skip to content

Commit

Permalink
Merge branch 'ns/feat/abi-parser' into ns/feat/abi-typegen
Browse files Browse the repository at this point in the history
  • Loading branch information
nedsalk committed Dec 17, 2024
2 parents e354ddc + 804feb1 commit 1c7f6a1
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 31 deletions.
8 changes: 5 additions & 3 deletions packages/abi/src/parser/specifications/v1/abi-type-mappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function mapMetadata(type: ResolvableType | ResolvedType) {
};

if (type.typeParamsArgsMap && type.metadataType?.typeParameters?.length) {
result.typeArguments = type.typeParamsArgsMap.map((t) => toTypeArgument(t[1]));
result.typeArguments = [...type.typeParamsArgsMap.values()].map((rt) => toTypeArgument(rt));
}

return result;
Expand Down Expand Up @@ -81,8 +81,10 @@ export function toAbiType(t: ResolvableType | ResolvedType): AbiConcreteType | A
metadataTypeId: t.metadataType?.metadataTypeId as number,
};

if (t.typeParamsArgsMap) {
result.typeParameters = t.typeParamsArgsMap.map(([, rt]) => toAbiType(rt) as AbiMetadataType);
if (t.typeParamsArgsMap && t.metadataType?.typeParameters?.length) {
result.typeParameters = [...t.typeParamsArgsMap.values()].map(
(rt) => toAbiType(rt) as AbiMetadataType
);
}
}

Expand Down
63 changes: 37 additions & 26 deletions packages/abi/src/parser/specifications/v1/resolvable-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,18 @@ export class ResolvableType {
concreteTypes: Map<string, AbiConcreteTypeV1>;
},
public metadataTypeId: number,
public typeParamsArgsMap: Array<[number, ResolvedType | ResolvableType]> | undefined
public typeParamsArgsMap: Map<number, ResolvedType | ResolvableType> | undefined
) {
this.metadataType = this.findMetadataType(metadataTypeId);
this.swayType = this.metadataType.type;
this.typeParamsArgsMap ??= this.metadataType.typeParameters?.map((tp) => [
tp,
new ResolvableType(this.abiTypeMaps, tp, undefined),
]);
this.typeParamsArgsMap ??=
this.metadataType.typeParameters &&
new Map(
this.metadataType.typeParameters.map((typeParameter) => [
typeParameter,
new ResolvableType(this.abiTypeMaps, typeParameter, undefined),
])
);

this.components = this.metadataType.components?.map((c) =>
this.createResolvableComponent(this, c)
Expand Down Expand Up @@ -82,8 +86,13 @@ export class ResolvableType {
private static mapTypeParametersAndArgs(
metadataType: AbiMetadataTypeV1,
args: (ResolvableType | ResolvedType)[]
): Array<[number, ResolvedType | ResolvableType]> | undefined {
return metadataType.typeParameters?.map((typeParameter, idx) => [typeParameter, args[idx]]);
): Map<number, ResolvedType | ResolvableType> | undefined {
return (
metadataType.typeParameters &&
new Map<number, ResolvedType | ResolvableType>(
metadataType.typeParameters.map((typeParameter, idx) => [typeParameter, args[idx]])
)
);
}

private createResolvableComponent(
Expand Down Expand Up @@ -176,9 +185,7 @@ export class ResolvableType {
* We check in the parent's typeParamsArgsMap if the metadata type we're solving for
* has been substituted with a different generic type, and then we use that generic type.
*/
const resolvableTypeParameter = parent.typeParamsArgsMap?.find(
([typeParameterId]) => typeParameterId === metadataType.metadataTypeId
)?.[1];
const resolvableTypeParameter = parent.typeParamsArgsMap?.get(metadataType.metadataTypeId);

return (
resolvableTypeParameter ??
Expand Down Expand Up @@ -227,7 +234,7 @@ export class ResolvableType {

private resolveInternal(
typeId: string | number,
typeParamsArgsMap: Array<[number, ResolvedType]> | undefined
typeParamsArgsMap: Map<number, ResolvedType> | undefined
): ResolvedType {
const resolvedType = new ResolvedType({
swayType: this.swayType,
Expand Down Expand Up @@ -263,9 +270,7 @@ export class ResolvableType {
* its corresponding type argument will be found in the typeArgs,
* which will be used to substitute the component with.
*/
const resolvedGenericType = typeArgs?.find(
([typeParameterId]) => type.metadataTypeId === typeParameterId
)?.[1];
const resolvedGenericType = typeArgs?.get(type.metadataTypeId);

if (resolvedGenericType) {
return {
Expand Down Expand Up @@ -301,8 +306,8 @@ export class ResolvableType {
}

private resolveTypeArgs(
typeParamsArgsMap: Array<[number, ResolvedType]> | undefined
): [number, ResolvedType][] | undefined {
typeParamsArgsMap: Map<number, ResolvedType> | undefined
): Map<number, ResolvedType> | undefined {
/**
* This case only happens when the metadata type is *implicitly* generic.
* The type itself doesn't have any type parameters that should be resolved,
Expand All @@ -314,31 +319,36 @@ export class ResolvableType {
return typeParamsArgsMap;
}

const newMap = new Map<number, ResolvedType>();

/**
* We resolve the type parameters of the underlying metadata type
* with the type arguments of the concrete type.
*/
return this.typeParamsArgsMap.map(([tp, value]) => {
this.typeParamsArgsMap.forEach((arg, typeParameter) => {
/**
* Some type parameters can already be resolved
* e.g. `struct MyStruct<E> { a: DoubleGeneric<E, u16> }`
* where the second type parameter of DoubleGeneric is already known.
*/
if (value instanceof ResolvedType) {
return [tp, value];
if (arg instanceof ResolvedType) {
newMap.set(typeParameter, arg);
return;
}

const resolved = typeParamsArgsMap?.find(
([typeParameterId]) => typeParameterId === value.metadataTypeId
);

/**
* The type parameter is either directly substituted with a type argument,
* or it's metadata type which accepts the type argument,
* so that metadata type needs to be resolved first.
*/
return resolved ?? [tp, value.resolveInternal(value.metadataTypeId, typeParamsArgsMap)];
const resolved =
typeParamsArgsMap?.get(arg.metadataTypeId) ??
arg.resolveInternal(arg.metadataTypeId, typeParamsArgsMap);

newMap.set(arg.metadataTypeId, resolved);
});

return newMap;
}

public resolve(concreteType: AbiConcreteTypeV1) {
Expand All @@ -348,8 +358,9 @@ export class ResolvableType {
});

const typeParamsArgsMap = concreteTypeArgs
? (ResolvableType.mapTypeParametersAndArgs(this.metadataType, concreteTypeArgs) as Array<
[number, ResolvedType]
? (ResolvableType.mapTypeParametersAndArgs(this.metadataType, concreteTypeArgs) as Map<
number,
ResolvedType
>)
: undefined;

Expand Down
4 changes: 2 additions & 2 deletions packages/abi/src/parser/specifications/v1/resolved-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ export class ResolvedType {
public swayType: string;
public typeId: string | number;
public components: ResolvedComponent[] | undefined;
public typeParamsArgsMap: Array<[number, ResolvedType]> | undefined;
public typeParamsArgsMap: Map<number, ResolvedType> | undefined;
public metadataType: AbiMetadataTypeV1 | undefined;

constructor(params: {
swayType: string;
typeId: string | number;
components?: ResolvedComponent[];
typeParamsArgsMap?: Array<[number, ResolvedType]>;
typeParamsArgsMap?: Map<number, ResolvedType>;
metadataType?: AbiMetadataTypeV1;
}) {
this.swayType = params.swayType;
Expand Down

0 comments on commit 1c7f6a1

Please sign in to comment.