Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | 156x 156x 156x 156x 10820x 10820x 2x 10818x 10818x 208x 208x 10610x 10610x 12x 10598x 3x 10595x 9247x 1348x 73x 1275x 12x 12x 12x 21713x 21713x 17113x 303x 4171x 111x 1x 1x 1x 9x 3x 4x 3x | /**
* TypeResolver - Converts string type representations to TType.
*
* This utility handles the conversion from the old string-based type system
* (e.g., "u32", "string<32>", "u8[10]") to the new TType discriminated union.
*/
import type TType from "../types/TType";
import TTypeUtils from "./TTypeUtils";
import PrimitiveKindUtils from "./PrimitiveKindUtils";
import ArrayDimensionText from "./ArrayDimensionText";
import invariant from "./invariant";
// Regex patterns for type parsing
const STRING_TYPE_PATTERN = /^string\s*<\s*(\d+)\s*>$/;
const ARRAY_TYPE_PATTERN = /^(.+?)(\[\s*[^\]]+\s*\])+$/;
const EXTERNAL_TYPE_PATTERN = /[:<>]/;
const ENUM_PREFIX_PATTERN = /^E[A-Z]/;
class TypeResolver {
/**
* Parse a string type representation and return the corresponding TType.
*
* @param typeString - String representation of a type (e.g., "u32", "string<32>", "u8[10]")
* @returns The corresponding TType object
* @throws Error if the type string is empty or invalid
*/
static resolve(typeString: string): TType {
const trimmed = typeString.trim();
if (trimmed === "") {
throw new Error("Cannot resolve empty type string");
}
// Check for string type: string<N>
const stringMatch = STRING_TYPE_PATTERN.exec(trimmed);
if (stringMatch) {
const capacity = Number.parseInt(stringMatch[1], 10);
return TTypeUtils.createString(capacity);
}
// Check for array type: baseType[dim1][dim2]...
const arrayMatch = ARRAY_TYPE_PATTERN.exec(trimmed);
if (arrayMatch) {
return TypeResolver.parseArrayType(trimmed, arrayMatch[1]);
}
// Check for external type (contains :: or < > for templates)
if (EXTERNAL_TYPE_PATTERN.test(trimmed)) {
return TTypeUtils.createExternal(trimmed);
}
// Check for primitive type
if (PrimitiveKindUtils.isPrimitive(trimmed)) {
return TTypeUtils.createPrimitive(trimmed);
}
// Check for enum (E prefix convention)
// LIMITATION: This heuristic assumes enums start with 'E' followed by uppercase.
// It may misclassify: enums without 'E' prefix, or structs named like 'EFoo'.
// For accurate resolution, use SymbolRegistry to check against known types.
if (ENUM_PREFIX_PATTERN.test(trimmed)) {
return TTypeUtils.createEnum(trimmed);
}
// Default to struct type
return TTypeUtils.createStruct(trimmed);
}
/**
* Parse an array type and return the TType.
*/
private static parseArrayType(fullType: string, baseTypeStr: string): TType {
// Issue #1127: shared with SymbolUtils.parseArrayDimensions. This used a
// base-10 parseInt, which read "0x10" as 0 and "8+1" as 8 -- a 16-element
// array reported as dimension 0, and an expression silently truncated.
const dimensions = ArrayDimensionText.parse(fullType);
// Resolve the base type (recursively handles string<N> as base type)
const elementType = TypeResolver.resolve(baseTypeStr.trim());
return TTypeUtils.createArray(elementType, dimensions);
}
/**
* Convert a TType back to its string representation.
*
* This is useful for round-trip compatibility and debugging.
*
* @param type - The TType object to convert
* @returns String representation of the type
*/
static getTypeName(type: TType): string {
// Not a diagnostic and not reachable from user input: 1.4 Resolve
// replaces every deferred type, so one arriving here means a pass ran out
// of order or a rebuilt symbol was dropped. Flattening it to `type.name`
// would emit the UNQUALIFIED name -- the silent wrong answer this exists to
// make impossible, and the one ADR-057 cannot recover from once the name
// is a string.
invariant(
type.kind !== "deferred",
"1.4 Resolve settles every deferred type before code generation names one",
);
switch (type.kind) {
case "primitive":
return type.primitive;
case "string":
return `string<${type.capacity}>`;
case "struct":
return type.name;
case "enum":
return type.name;
case "bitmap":
return type.name;
case "callback":
return type.name;
case "register":
return type.name;
case "external":
return type.name;
case "array": {
const elementName = TypeResolver.getTypeName(type.elementType);
const dims = type.dimensions.map((d) => `[${d}]`).join("");
return `${elementName}${dims}`;
}
}
}
}
export default TypeResolver;
|