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 | 378x 379x 375x 375x 374x 1x 492x | /**
* QualifiedNameGenerator - C-style name generation for C-Next symbols
*
* Provides transpiled C name generation for use in the output layer.
* Delegates to ScopeUtils for the actual implementation to avoid duplication
* with the types layer.
*
* Design decisions:
* - Lives in output layer (codegen) since it generates C output
* - Delegates to ScopeUtils for symbol-based name generation
* - Provides string-based methods for backward compatibility
* - Handles nested scopes: Outer.Inner.func -> Outer_Inner_func
* - Global scope functions keep their bare names
*/
import type IProgram from "../types/IProgram";
import type IFunctionSymbol from "../types/symbols/IFunctionSymbol";
import ScopeUtils from "./ScopeUtils";
class QualifiedNameGenerator {
// ============================================================================
// Symbol-based methods (preferred)
// ============================================================================
/**
* Generate the transpiled C name for a function.
*
* For global scope functions, returns the bare name (e.g., "main").
* For scoped functions, returns "Scope_name" (e.g., "Test_fillData").
* For nested scopes, returns "Outer_Inner_name" (e.g., "Outer_Inner_deepFunc").
*
* Delegates to ScopeUtils.getTranspiledCName() to avoid duplication.
*/
static forFunction(func: IFunctionSymbol): string {
return ScopeUtils.getTranspiledCName(func);
}
// #1298 removed `getScopePath`, a delegate to a `ScopeUtils` walk that no
// longer exists: a scope's path is now a field on every symbol, so there is
// nothing left to compute or to delegate.
// ============================================================================
// String-based methods (for transition - use symbol-based when possible)
// ============================================================================
/**
* Generate a qualified function name for a function named inside a scope.
*
* Takes the scope PATH. #1285 replaced a leaf `string` with the scope symbol,
* because the caller had to flatten a symbol to its leaf name and this had to
* look it back up, losing any outer chain in between. #1298 makes it a string
* again -- but the WHOLE path, which loses nothing, and which the caller already
* holds.
*
* Falls back to qualifying the bare name when the function is not registered.
*/
static forFunctionInScope(
scopePath: string,
funcName: string,
program: IProgram | null,
): string {
// #1452 box 3: the scope graph arrives as an argument rather than off a
// global. `utils/` authors no facts and now reaches for none either.
if (!program) return ScopeUtils.qualifyInScope(funcName, scopePath);
const func = program.resolveFunction(funcName, scopePath);
if (func) {
return this.forFunction(func);
}
return ScopeUtils.qualifyInScope(funcName, scopePath);
}
/**
* The C name a bare member of `scope` is emitted under. **The canonical
* spelling for `output/`.**
*
* A one-line delegate to `ScopeUtils.qualifyInScope`, so there is one
* implementation and no divergence to fix. What it settles is which of the two
* public NAMES a codegen call site uses, because the two take their arguments in
* opposite orders -- `forMember(scopePath, name)` against `qualifyInScope(name,
* scopePath)`. Two spellings of one decision sixty lines apart in a file is how a
* silently inverted call gets written by the next person editing nearby (#1357
* review).
*
* `ScopeUtils.qualifyInScope` was the door for `logic/`, which could not import
* `output/`, where this class lived (depcruise `logic-cannot-import-output`).
* #1445 moved this class to `utils/` and #1444 dissolved `logic/` into 1.1
* Discover, so the rule is retired. Both doors remain because both have
* callers. This one delegates and decides nothing, so they cannot disagree.
*/
static forMember(scopePath: string, memberName: string): string {
return ScopeUtils.qualifyInScope(memberName, scopePath);
}
}
export default QualifiedNameGenerator;
|