Version: 2.0
Date: 2026-02-23
Status: Draft
Parallel to: ../profiles/ (Domain Extension Mechanism, §23)
A Translation Guide is a structured document that teaches an LLM how to translate between a language and LMPL as the intermediate representation. Guides are the primary extension mechanism for LMPL's translation capability — the point where specification meets practice.
Translation Guides are to LMPL what phrasebooks are to a language: they don't change the language itself, they teach how to say specific things in specific contexts. The LMPL language reference defines the core vocabulary; Translation Guides teach an LLM how to move between source code and that vocabulary in both directions.
- Structured guidance for LLM-mediated translation through LMPL
- Normative for their language (the authoritative source on how to translate language X via LMPL)
- Standalone documents that compose with each other multiplicatively
- The "rubber-meets-the-road" extension point — where LMPL theory becomes translation practice
- Not new language constructs. Guides do not add types, blocks, or semantic rules to LMPL. That is the role of Domain Profiles (§23).
- Not LLM prompts. Guides are reference documents that an LLM consults, not system prompts to be injected verbatim. An orchestration layer selects and presents relevant guide sections to the LLM.
- Not test suites. Guides include validation cases, but comprehensive test suites are separate artifacts.
Translation Guides follow a naming convention based on their scope:
Pattern: extensions/translation-guides/languages/{language}.md
Purpose: Cover a language's full relationship to LMPL — used when lifting FROM the language and when lowering TO it.
Examples: extensions/translation-guides/languages/sas.md, extensions/translation-guides/languages/python-pandas.md, extensions/translation-guides/languages/sql.md
A Language Guide is bidirectional. It documents:
- The language's constructs and their LMPL equivalents (used for lifting)
- LMPL constructs and their idiomatic expression in this language (used for lowering)
- Source-capture directives (
@sas_data_step,@sas_proc, etc.) for lifting - Target-generation directives (
@prefer_vectorised,@streaming_safe, etc.) for lowering - Semantic gaps between this language and LMPL, with directional resolutions
- Idiom preferences when generating code in this language
Sections within the guide address direction-specific concerns where needed. "Idiom Preferences" applies when lowering to this language. "Implicit State" applies when lifting from it. The mapping between language constructs and LMPL is inherently bidirectional — if DATA step ↔ filter/derive pipeline, that mapping serves both directions.
Pattern: extensions/translation-guides/pairs/{source}-to-{target}.md
Purpose: Source-to-target-specific patterns that go beyond what two Language Guides provide individually.
Example: extensions/translation-guides/pairs/sas-to-python.md
Pair Guides are optional. They exist for high-value translation pairs where the combination of two Language Guides misses patterns specific to the source→target direction. They reference the component Language Guides rather than duplicating them.
N Language Guides give N × (N-1) directed translation pairs through the LMPL pivot. Each new Language Guide enables translation to and from every existing language:
SAS guide ←→ LMPL ←→ Python guide
↕
SQL guide
With 3 Language Guides (SAS, Python, SQL), you get 6 directed translation pairs: SAS→Python, Python→SAS, SAS→SQL, SQL→SAS, Python→SQL, SQL→Python. Each new Language Guide adds 2 × (N-1) new pairs, where N is the current guide count. Pair Guides add source-to-target-specific refinements on top of this compositional base.
Every Language Guide must include the following sections. The section ordering below is normative.
Metadata identifying the guide's scope:
| Field | Description | Example |
|---|---|---|
| Language | Language this guide covers | SAS 9.4 |
| Primary Direction | Optional — if this guide is predominantly used for lifting or lowering | Lifting (legacy migration source) |
| Target Libraries | Preferred libraries when lowering to this language | pandas 2.x, numpy |
| Scope | What subset of the language this guide covers | DATA steps, PROC SORT, PROC MEANS, PROC FREQ, macro language |
| Out of Scope | What is explicitly not covered | PROC IML, ODS output, SAS/GRAPH |
| Prerequisites | Required knowledge, other guides referenced | LMPL Language Reference v0.3, familiarity with the language |
| LMPL Profiles | Domain profiles relevant to this guide | None (core LMPL only) |
A systematic bidirectional mapping between the language's constructs and their LMPL equivalents. Modeled on Appendix B of the LMPL specification.
Required columns:
| Language Construct | LMPL Equivalent | Notes |
|---|---|---|
| Language syntax/concept | LMPL construct(s) | Semantic nuances, direction-specific considerations |
The mapping is read left-to-right when lifting (language → LMPL) and right-to-left when lowering (LMPL → language). The Notes column should flag direction-specific concerns where relevant (e.g., "When lifting: capture implicit sort stability; When lowering: use stable=True").
The mapping table should be comprehensive for the stated scope. Every construct listed in the Overview's scope must appear in this table.
A catalog of semantic divergences between this language and LMPL, with directional resolution strategies. Each entry documents a case where the language and LMPL disagree on meaning — the exact situations where translation produces subtly wrong code.
Required fields per entry:
| Field | Description |
|---|---|
| Gap ID | Unique identifier (e.g., GAP-001) |
| Category | Classification (e.g., missing values, type coercion, sort order, date handling) |
| Language Behavior | What this language does |
| LMPL Behavior | What LMPL specifies or assumes |
| Resolution | Directional: "When lifting: ...; When lowering: ..." |
| LMPL Annotation | The @semantic_change annotation documenting this gap |
| Test Case | Input/output pair that exposes the gap |
Example entry:
| Field | Value |
|---|---|
| Gap ID | GAP-001 |
| Category | Missing values |
| Language Behavior | SAS sorts missing values before all non-missing values |
| LMPL Behavior | LMPL's sort does not specify missing value position |
| Resolution | When lifting: annotate with @semantic_change noting SAS missing-first behavior. When lowering: use target-appropriate mechanism (e.g., na_position='first' in pandas) |
| LMPL Annotation | @semantic_change("SAS missing sorts before all values; target language may differ") |
| Test Case | Input: [3, missing, 1, missing, 2] → SAS order: [., ., 1, 2, 3] |
Where the language involves multi-layer constructs (macros, templates) or embedded guest languages (SQL, regex), the guide must include strategy decision tables specifying which LMPL strategy to apply.
For multi-layer languages (referencing §20):
| Condition | Strategy | Rationale |
|---|---|---|
| Language pattern | inline / preserve / parameterise |
Why this strategy fits |
For embedded guest languages (referencing §21):
| Condition | Strategy | Rationale |
|---|---|---|
| Embedding pattern | preserve / lift / rewrite |
Why this strategy fits |
Guides for languages without macros or embeddings may mark this section "Not applicable" with a brief explanation.
Conventions that guide the LLM toward idiomatic output when lowering to this language. This section prevents the LLM from producing "correct but ugly" translations.
Required elements:
- Preferred patterns — The idiomatic way to express common operations in this language (e.g., "use method chaining for pandas operations, not intermediate variables")
- Anti-patterns — Patterns to avoid (e.g., "do not iterate over DataFrame rows with
forloops; use vectorized operations") - Library selection rationale — Why specific libraries are preferred and when alternatives are appropriate
- Naming conventions — Variable, function, and module naming guidance for this language
At minimum, three worked examples demonstrating translation via this guide:
| Example | Complexity | Purpose |
|---|---|---|
| Simple | Single construct, no semantic gaps | Demonstrates basic mapping |
| Medium | Multiple constructs, 1-2 semantic gaps | Demonstrates gap handling and strategy selection |
| Complex | Multi-layer or embedded language, multiple gaps | Demonstrates full guide coverage |
Each example must include:
- Language code — Complete, runnable source program
- LMPL — The intermediate representation with annotations and contracts
- Round-trip demonstration — Where appropriate, show the full cycle: Language → LMPL (lifting) or LMPL → Language (lowering), or the complete round-trip
- Commentary — Explanation of decisions made, gaps handled, strategies chosen
Examples may demonstrate lifting, lowering, or both. A well-constructed example showing Language → LMPL → Language demonstrates the guide's bidirectional coverage.
Input/output pairs for testing translation quality. Distinct from worked examples — validation cases are concise, focused on edge cases and known failure modes.
Required elements:
- Correctness cases — Language/LMPL pairs where the expected output is known (minimum 5). Cases may test lifting, lowering, or both.
- Edge cases — Inputs that test semantic gap handling (minimum 3)
- Known failure modes — Inputs where LLM translation is known to fail or produce incorrect results, with description of the failure and workarounds
Validation cases should be small enough to evaluate by inspection. Full integration tests belong in a separate test suite, not in the guide.
A complete list of annotations used by this guide, covering both directions:
| Annotation | Category | Purpose |
|---|---|---|
e.g., @sas_data_step |
Source capture | Marks LMPL block as originating from a SAS DATA step (used when lifting from this language) |
e.g., @prefer_vectorised |
Target generation | Instructs lowering to prefer vectorized operations (used when lowering to this language) |
e.g., @semantic_change |
Fidelity | Documents a semantic divergence between this language and LMPL |
This section references the annotation definitions in §17 of the LMPL specification. Guides may define new source-capture directives not present in §17 — these must be documented here with full definitions. Source-capture directives and target-generation directives coexist in a single table, clearly categorized.
Detailed guidance for library usage when lowering to this language. Appropriate when the language has multiple library choices (e.g., pandas vs Polars vs DuckDB for Python data operations) and the guide needs to provide detailed API-level guidance.
Includes:
- Library version requirements
- API patterns for common LMPL constructs
- Performance characteristics and selection criteria
- Migration notes between library versions
How this Language Guide interacts with other Language Guides or Pair Guides. Appropriate when:
- This guide expects certain patterns from specific source languages (e.g., "LMPL lifted from SAS frequently includes
@semantic_changefor missing values — this guide's lowering section handles those annotations specifically") - Pair Guides exist that extend this guide for specific translation directions
Language Guides are normative for their language. When an LLM translates via LMPL using a particular language as source or target, the relevant Language Guide is the authoritative source on how that language relates to LMPL.
Language Guides:
- May define new source-capture directives (e.g.,
@r_formula,@spss_syntax) following the annotation syntax of §17 - May specify idiom preferences and library choices for their language
- May document semantic gaps specific to their language
- May reference Domain Profiles when relevant (e.g., a guide for translating financial SAS code may reference
@profile("financial")) - May NOT add new LMPL types or modify the core type system (that is the role of Domain Profiles, §23)
- May NOT change core LMPL semantics (e.g., redefine how
missingpropagates) - May NOT modify the LMPL grammar (e.g., add new block forms or keywords)
Guides are versioned independently of the LMPL specification and of each other. Each guide declares the LMPL specification version it targets in its Overview section.
When the LMPL specification introduces changes that affect a guide's construct mappings or semantic gap registry, the guide must be updated. The guide's version number increments; a changelog entry describes the update.
A guide is considered complete when:
- All constructs in the stated scope appear in the construct mapping table
- All known semantic gaps between the language and LMPL are registered
- At least 3 worked examples are provided (simple, medium, complex)
- At least 5 correctness validation cases and 3 edge cases are provided
- All annotations used are documented in the annotations reference
Translation Guides and Domain Profiles are the two extension mechanisms for LMPL. They are complementary, not competing:
| Dimension | Domain Profiles (§23) | Translation Guides |
|---|---|---|
| Extends | LMPL's type system and semantics | LMPL's translation capability |
| Analogy | Dialect dictionary — adds new vocabulary | Phrasebook — teaches how to say things in specific languages |
| Adds new types? | Yes (e.g., tensor, decimal, message) |
No |
| Adds new annotations? | Yes (e.g., @trainable, @accrual_basis) |
Source-capture directives only |
| Adds new statement forms? | Yes (e.g., agent_loop, resource, transaction) |
No |
| Changes core semantics? | Adds domain-specific constraints | Never |
| File location | extensions/profiles/{domain}.md |
extensions/translation-guides/languages/{language}.md |
| Scope | Domain of application (ML, finance, security) | Language (SAS, Python, SQL) |
| Interaction | Profile must be declared with @profile annotation |
Guide is selected by orchestration based on source/target language |
| Composition | Module may declare at most one profile | Multiple Language Guides used simultaneously (one per endpoint of translation) |
- "I need a new type for my domain" → Domain Profile
- "I need to translate language X to language Y" → Language Guides for X and Y (+ optional Pair Guide)
- "I need domain-specific types AND translation for that domain" → Domain Profile for types + Language Guides for translation, referencing each other
The LMPL language reference (v0.3) already contains substantial material that maps to Language Guide sections. The following table demonstrates that a SAS Language Guide (extensions/translation-guides/languages/sas.md) is approximately 70% written:
| Guide Section | Spec Source | Coverage | Status |
|---|---|---|---|
| Overview | §1 (Introduction), §22 (Translation Workflow) | Language/scope/prerequisites | Complete |
| Construct Mapping Table | Appendix B (SAS Construct Mapping) | 22 SAS constructs ↔ LMPL (bidirectional) | Complete |
| Semantic Gap Registry | §22 (Translation Workflow, gap documentation) | 5 categories: missing/null, sort order, type coercion, dates, strings | Substantial |
| Strategy Decision Tables — Macros | §20 (Multi-Layer Requirements) | 3 strategies (inline/preserve/parameterise) with 6 selection criteria |
Complete |
| Strategy Decision Tables — Embedding | §21 (Foreign Language Embedding) | 3 strategies (preserve/lift/rewrite) with selection criteria |
Complete |
| Worked Examples | applications/sas-to-python/ |
1 complete example (customer segmentation with source, LMPL, and Python target) | Partial (need 2+ more) |
| Idiom Preferences | §17 (@prefer_vectorised, @allow_sql directives) |
Directives exist but not organized as preferences | Partial |
| Validation Cases | — | Not present in spec | Missing |
| Library Reference | @target_libraries annotation |
Annotation exists but no detailed library guidance | Missing |
| Annotations Reference | §17 (Annotations and Metadata) | Source-capture and target-generation directives fully defined | Complete |
To produce a complete extensions/translation-guides/languages/sas.md:
- Extract construct mapping from Appendix B (copy, reformat as bidirectional table)
- Extract semantic gaps from §22 (expand to registry format with directional resolutions and test cases)
- Extract strategy tables from §20 and §21 (copy, add SAS-specific rationale)
- Extract worked example from §24 (copy as-is for complex example)
- Write 2 additional worked examples (simple DATA step, medium PROC with macro)
- Write idiom preferences section (SAS-specific lowering guidance — if targeting SAS from another language)
- Write validation cases (5+ correctness, 3+ edge cases, known failure modes)
- Write library reference (for lowering to SAS: SAS/BASE, SAS/STAT, etc.)
Steps 1-4 are extraction and reformatting. Steps 5-8 are new content. This is the first strategic priority identified in the competitive landscape response.