# Languages



Every language-specific concern — what a file, an import, or a
declaration looks like; which identifiers are legal; how names
sanitize — lives in a per-language package. `@skmtc/lang-typescript`
is the production language layer; other language layers are pre-alpha
and not published for general use.

## Where the language enters [#where-the-language-enters]

The language enters the DSL class hierarchy at the lang package's
**snippet base** (`TsSnippet`), which carries a static `lang`.
Projection bases are built by the lang package's veneers
(`toTsModelProjectionBase`, `toTsOasOperationProjectionBase`, …), so
every projection inherits that static. The engine's Drivers read it
ephemerally when they create files and build Definitions — nothing in
core persists a language reference. Rendering lives on each DSL
object's own `toString()` in its language subclass; there is no
central renderer or visitor.

## What a lang package owns [#what-a-lang-package-owns]

For TypeScript, the package supplies:

* **The `Lang` object** — the four neutral factories Drivers call
  (`createFile` / `toDefinition` / `toImport` / `toIdentifier`).
* **The snippet base** — `TsSnippet`, where the language enters the
  hierarchy.
* **Projection-base veneers** — `toTs*ProjectionBase`, pre-binding the
  snippet base onto core's neutral factories.
* **The register family** — `register` / `defineAndRegister` and the
  concise `TsRegisterArgs` vocabulary (`imports` / `reExports` /
  `definitions`).
* **Concrete file, import, and definition classes** — `TsFile`,
  `TsImport`, `TsReExport`, `TsDefinition`.
* **Identifier factories and the kind vocabulary** — `createVariable` /
  `createType`.
* **Name sanitization and syntax helpers** — `sanitizePropertyName`,
  `List`, `FunctionParameter`, `toPathTemplate`, …

Generators never construct the file/import/definition classes
directly — the register functions and the engine's Drivers build them.
A generator newing up a `TsImport` almost certainly wanted
`register({ imports })`.

## Languages differ honestly [#languages-differ-honestly]

The design rule: don't surface one language's concepts in another, and
don't neutralize concepts until they lose meaning. Core carries only
opaque discriminants (`kind`, `exported`); each language package gives
them syntactic meaning and admits exactly what the language has. A
language without re-exports has no `reExports` field in its register
vocabulary — registering one is a compile error, not a silent no-op —
and each language's keyword mapping throws on a foreign kind rather
than guessing.

## Grammar vs policy [#grammar-vs-policy]

A lang package renders **grammar**; a generator decides **policy**.
`TsImport` knows how to render a type-only import; *deciding* that a
symbol is type-only is the generator's (or Driver's) call. Choices
like which validation library an output uses never belong in a lang
package — swapping that flavor means a sibling generator, not a lang
change.

## See also [#see-also]

* [projections-and-snippets.md](/docs/concepts/projections-and-snippets) — the
  DSL the lang packages plug into
* [how-generators-produce-output.md](/docs/concepts/how-generators-produce-output)
  — the register path end to end
* [stringable-composition.md](/docs/concepts/stringable-composition) — why
  rendering lives on `toString()`
