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 | 93x 93x 1450x 19x 3x 120x | /**
* ReservedCnxName - the single source of truth for names the transpiler invents.
*
* ADR-063 part 2 reserves the `cnx_` prefix, compared case-insensitively, for
* every name that corresponds to no user declaration: temporaries, the strlen
* cache, overflow helpers, include guards. A user identifier may not begin with
* it (E0202), which is what makes the transpiler's namespace and the user's
* disjoint.
*
* Before this module each family spelled its own convention — `_tmp<N>`,
* `_<var>_len`, `_cnx_tmp_<N>`, `cnx_clamp_*`, `<BASENAME>_H` — and three of the
* five chose shapes a user could declare. Issue #1131 verified the consequence:
* a user global `_msg_len` was shadowed by the generated strlen cache and every
* later read silently bound to the wrong storage, with a clean `-Wall -Wextra`
* compile and exit 0. Route all invented names through here.
*
* NOT for qualified user names (`Scope__member`). Those are built by
* QualifiedCName, and the two must not be confused: `__` asserts "qualified user
* name, component boundary here", which a temporary has no business claiming.
*/
class ReservedCnxName {
/**
* The reserved prefix, in the case used for C identifiers.
*
* Rejected in user declarations by E0202 (IdentifierSyntaxAnalyzer).
*/
static readonly PREFIX = "cnx_";
/**
* The reserved prefix in the case used for macros.
*
* Include guards are uppercase by universal C convention, which is why the
* E0202 comparison is case-insensitive: one rule covers both spellings.
*/
static readonly MACRO_PREFIX = "CNX_";
/**
* Whether an identifier sits in the transpiler's reserved namespace.
*
* Prefix-only and case-insensitive, exactly as ADR-063 states. `my_cnx_buffer`
* is legal — a prefix is all that is needed to keep the namespaces disjoint,
* so that is all this checks.
*/
static isReserved(identifierName: string): boolean {
return identifierName.toLowerCase().startsWith(ReservedCnxName.PREFIX);
}
/**
* Name for a generated temporary, e.g. `cnx_tmp3`.
*
* Replaces the former `_tmp<N>` (slice-assignment unroll) and `_cnx_tmp_<N>`
* (argument temporary). Both drew from the same counter, so unifying the
* spelling cannot make two live temporaries collide.
*/
static temporary(counter: number): string {
return `${ReservedCnxName.PREFIX}tmp${counter}`;
}
/**
* Name for the cached `strlen` of a string variable, e.g. `cnx_len_message`.
*
* The variable name is a suffix rather than an infix (the former shape was
* `_<var>_len`) so that every generated name reads prefix-first.
*/
static stringLengthCache(variableName: string): string {
return `${ReservedCnxName.PREFIX}len_${variableName}`;
}
/**
* Name for a clamping overflow helper, e.g. `cnx_clamp_add_u8`.
*
* This family already conformed before ADR-063 part 2; it is routed through
* here so the prefix has exactly one definition.
*/
static clampHelper(operation: string, cnxType: string): string {
return `${ReservedCnxName.PREFIX}clamp_${operation}_${cnxType}`;
}
}
export default ReservedCnxName;
|