@typra/emitter 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/src/cleanup/generated-file.d.ts +6 -0
  2. package/dist/src/cleanup/generated-file.js +61 -0
  3. package/dist/src/cli.d.ts +2 -0
  4. package/dist/src/cli.js +110 -0
  5. package/dist/src/decorators.d.ts +56 -0
  6. package/dist/src/decorators.js +177 -0
  7. package/dist/src/emitter.d.ts +13 -0
  8. package/dist/src/emitter.js +137 -0
  9. package/dist/src/generate.d.ts +86 -0
  10. package/dist/src/generate.js +104 -0
  11. package/dist/src/index.d.ts +4 -0
  12. package/dist/src/index.js +5 -0
  13. package/dist/src/ir/ast.d.ts +235 -0
  14. package/dist/src/ir/ast.js +589 -0
  15. package/dist/src/ir/declarations.d.ts +364 -0
  16. package/dist/src/ir/declarations.js +23 -0
  17. package/dist/src/ir/expansion.d.ts +140 -0
  18. package/dist/src/ir/expansion.js +407 -0
  19. package/dist/src/ir/lower.d.ts +53 -0
  20. package/dist/src/ir/lower.js +480 -0
  21. package/dist/src/ir/utilities.d.ts +12 -0
  22. package/dist/src/ir/utilities.js +39 -0
  23. package/dist/src/ir/visitor.d.ts +29 -0
  24. package/dist/src/ir/visitor.js +48 -0
  25. package/dist/src/languages/csharp/driver.d.ts +5 -0
  26. package/dist/src/languages/csharp/driver.js +315 -0
  27. package/dist/src/languages/csharp/emitter.d.ts +33 -0
  28. package/dist/src/languages/csharp/emitter.js +1140 -0
  29. package/dist/src/languages/csharp/scaffolding.d.ts +18 -0
  30. package/dist/src/languages/csharp/scaffolding.js +591 -0
  31. package/dist/src/languages/csharp/test-emitter.d.ts +43 -0
  32. package/dist/src/languages/csharp/test-emitter.js +274 -0
  33. package/dist/src/languages/csharp/visitor.d.ts +14 -0
  34. package/dist/src/languages/csharp/visitor.js +79 -0
  35. package/dist/src/languages/go/driver.d.ts +12 -0
  36. package/dist/src/languages/go/driver.js +128 -0
  37. package/dist/src/languages/go/emitter.d.ts +33 -0
  38. package/dist/src/languages/go/emitter.js +879 -0
  39. package/dist/src/languages/go/scaffolding.d.ts +18 -0
  40. package/dist/src/languages/go/scaffolding.js +53 -0
  41. package/dist/src/languages/go/test-emitter.d.ts +20 -0
  42. package/dist/src/languages/go/test-emitter.js +300 -0
  43. package/dist/src/languages/go/visitor.d.ts +14 -0
  44. package/dist/src/languages/go/visitor.js +78 -0
  45. package/dist/src/languages/markdown/driver.d.ts +19 -0
  46. package/dist/src/languages/markdown/driver.js +408 -0
  47. package/dist/src/languages/python/driver.d.ts +14 -0
  48. package/dist/src/languages/python/driver.js +372 -0
  49. package/dist/src/languages/python/emitter.d.ts +31 -0
  50. package/dist/src/languages/python/emitter.js +856 -0
  51. package/dist/src/languages/python/scaffolding.d.ts +33 -0
  52. package/dist/src/languages/python/scaffolding.js +279 -0
  53. package/dist/src/languages/python/test-emitter.d.ts +29 -0
  54. package/dist/src/languages/python/test-emitter.js +388 -0
  55. package/dist/src/languages/python/visitor.d.ts +14 -0
  56. package/dist/src/languages/python/visitor.js +65 -0
  57. package/dist/src/languages/rust/driver.d.ts +13 -0
  58. package/dist/src/languages/rust/driver.js +624 -0
  59. package/dist/src/languages/rust/emitter.d.ts +45 -0
  60. package/dist/src/languages/rust/emitter.js +1596 -0
  61. package/dist/src/languages/rust/visitor.d.ts +25 -0
  62. package/dist/src/languages/rust/visitor.js +153 -0
  63. package/dist/src/languages/typescript/driver.d.ts +8 -0
  64. package/dist/src/languages/typescript/driver.js +209 -0
  65. package/dist/src/languages/typescript/emitter.d.ts +42 -0
  66. package/dist/src/languages/typescript/emitter.js +904 -0
  67. package/dist/src/languages/typescript/scaffolding.d.ts +32 -0
  68. package/dist/src/languages/typescript/scaffolding.js +303 -0
  69. package/dist/src/languages/typescript/test-emitter.d.ts +23 -0
  70. package/dist/src/languages/typescript/test-emitter.js +204 -0
  71. package/dist/src/languages/typescript/visitor.d.ts +14 -0
  72. package/dist/src/languages/typescript/visitor.js +64 -0
  73. package/dist/src/lib.d.ts +33 -0
  74. package/dist/src/lib.js +101 -0
  75. package/dist/src/testing/index.d.ts +2 -0
  76. package/dist/src/testing/index.js +8 -0
  77. package/dist/src/testing/test-context.d.ts +63 -0
  78. package/dist/src/testing/test-context.js +355 -0
  79. package/fixtures/shapes/main.tsp +43 -0
  80. package/fixtures/tspconfig.yaml +13 -0
  81. package/package.json +76 -0
  82. package/src/lib/main.tsp +110 -0
@@ -0,0 +1,364 @@
1
+ /**
2
+ * Declaration IR — Type-level code generation for the emitter.
3
+ *
4
+ * This module defines the "declaration" IR that replaces Nunjucks templates.
5
+ * Where the Expression IR (expansion.ts) handles factory/coercion bodies,
6
+ * the Declaration IR handles entire type definitions: structs, fields,
7
+ * load/save methods, polymorphic dispatch, collection helpers, and factories.
8
+ *
9
+ * Architecture:
10
+ * TypeNode graph → lowerFile() → FileDecl → emitPythonFile() → .py code
11
+ * → emitRustFile() → .rs code
12
+ * → emitTypeScriptFile() → .ts code
13
+ * → emitCSharpFile() → .cs code
14
+ * → emitGoFile() → .go code
15
+ *
16
+ * The lowering pass (lower.ts) converts the TypeNode graph into FileDecl trees.
17
+ * Per-language emitter functions walk the FileDecl tree to produce code.
18
+ *
19
+ * Key design principle: PropertyCategory is the fundamental 5-way classification
20
+ * that drives ALL per-property code generation across all languages.
21
+ */
22
+ import { TypeName } from "./ast.js";
23
+ import { Expr } from "./expansion.js";
24
+ /**
25
+ * Every property in the type system falls into exactly one of these categories.
26
+ * This classification determines:
27
+ * - Type annotation in each language
28
+ * - Default value
29
+ * - Load (deserialization) pattern
30
+ * - Save (serialization) pattern
31
+ * - Whether a collection helper is generated
32
+ *
33
+ * Templates previously computed this via chains of `if isScalar && isCollection && !isDict`.
34
+ * Now it's classified once in the lowering pass.
35
+ */
36
+ export type PropertyCategory = {
37
+ kind: "scalar";
38
+ scalarType: string;
39
+ } | {
40
+ kind: "complex";
41
+ typeName: string;
42
+ } | {
43
+ kind: "collection_scalar";
44
+ scalarType: string;
45
+ } | {
46
+ kind: "collection_complex";
47
+ typeName: string;
48
+ } | {
49
+ kind: "dict";
50
+ };
51
+ /**
52
+ * Represents a named string-literal enum type (e.g., `Role`, `AuthenticationMode`).
53
+ * Derived from TypeSpec `alias X = "a" | "b" | "c"` unions.
54
+ *
55
+ * Language emitters use this to produce:
56
+ * - Python: `Role = Literal["system", "user", ...]`
57
+ * - TypeScript: `type Role = "system" | "user" | ...`
58
+ * - C#: `public enum Role { ... }` (with JSON string conversion)
59
+ * - Rust: `pub enum Role { ... }` (with serde rename_all)
60
+ * - Go: `type Role string` with const block
61
+ */
62
+ export interface EnumDef {
63
+ /** Enum type name (PascalCase from the TypeSpec alias, e.g., "Role") */
64
+ name: string;
65
+ /** Known string values (e.g., ["system", "user", "assistant", "developer", "tool"]) */
66
+ values: string[];
67
+ /** True when the alias includes `| string` — accepts arbitrary strings beyond the known values */
68
+ isOpen: boolean;
69
+ }
70
+ /**
71
+ * Represents an entire generated source file.
72
+ * Contains one or more types (parent + children for polymorphic types),
73
+ * resolved imports, and file-level metadata.
74
+ */
75
+ export interface FileDecl {
76
+ /** Primary type name (used for file naming) */
77
+ typeName: TypeName;
78
+ /** All types defined in this file (parent first, then children) */
79
+ types: TypeDecl[];
80
+ /** Resolved imports — each entry maps a module to the symbols imported from it */
81
+ imports: ImportRef[];
82
+ /** Whether any type in the file is abstract */
83
+ containsAbstract: boolean;
84
+ /** String-literal enum types used by fields in this file */
85
+ enums: EnumDef[];
86
+ /** Semantic group derived from TSP source subfolder (e.g. "connection", "tools"). Empty string for root-level files. */
87
+ group: string;
88
+ }
89
+ /**
90
+ * A single import statement grouping: one module, multiple symbols.
91
+ */
92
+ export interface ImportRef {
93
+ /** Module/file to import from (e.g., "ContentPart" in Python, "content-part" in TS) */
94
+ module: string;
95
+ /** Symbols imported from that module (e.g., ["ContentPart", "TextPart"]) */
96
+ names: string[];
97
+ /** Semantic group of the imported module (e.g. "connection"). Empty string for root-level modules. */
98
+ group: string;
99
+ }
100
+ /**
101
+ * Represents a complete type definition (class/struct/dataclass).
102
+ * Contains everything needed to generate the type and all its methods.
103
+ */
104
+ export interface TypeDecl {
105
+ /** Type name */
106
+ typeName: TypeName;
107
+ /** Parent type name (for inheritance) */
108
+ base: TypeName | null;
109
+ /** Whether this type is abstract (Python: ABC, C#: abstract, TS: abstract) */
110
+ isAbstract: boolean;
111
+ /** Whether this type is a protocol interface (Python: Protocol, TS: interface, Rust: trait, C#: interface, Go: interface) */
112
+ isProtocol: boolean;
113
+ /** Human-readable description for docstrings/comments */
114
+ description: string;
115
+ /** All fields defined on this type */
116
+ fields: FieldDecl[];
117
+ /** The property name that receives scalar coercion value, if any */
118
+ coercionProperty: string | null;
119
+ /** Load method specification */
120
+ load: LoadDecl;
121
+ /** Save method specification */
122
+ save: SaveDecl;
123
+ /** Factory methods (reuse Expr IR for bodies) */
124
+ factories: FactoryDecl[];
125
+ /** Collection helper methods (load_items/save_items for complex collections) */
126
+ collectionHelpers: CollectionHelperDecl[];
127
+ /** Polymorphic dispatch specification (if this type has a discriminator) */
128
+ polymorphicDispatch: PolymorphicDispatchDecl | null;
129
+ /** Method stubs to be implemented in extension modules */
130
+ methods: MethodStubDecl[];
131
+ /** Wire conversion specification (generated when any field has knownAs mappings) */
132
+ wire: WireDecl | null;
133
+ }
134
+ /**
135
+ * Represents a single field on a type.
136
+ * The category determines ALL code generation patterns for this field.
137
+ */
138
+ export interface FieldDecl {
139
+ /** Original property name from TypeSpec (camelCase) */
140
+ name: string;
141
+ /** Type name for annotations */
142
+ typeName: TypeName;
143
+ /** The fundamental classification that drives code generation */
144
+ category: PropertyCategory;
145
+ /** Whether this field is optional (None/null/nil default) */
146
+ isOptional: boolean;
147
+ /** Default value for the field (primitives only) */
148
+ defaultValue: string | number | boolean | null;
149
+ /** Allowed string values (for enum-like constraints) */
150
+ allowedValues: string[];
151
+ /** Named enum type for this field (e.g., "Role"), null if not an enum field */
152
+ enumName: string | null;
153
+ /** True when the enum includes a bare `string` variant (open — accepts any string) */
154
+ isOpenEnum: boolean;
155
+ /** Human-readable description for docstrings */
156
+ description: string;
157
+ /** Wire name mappings per provider (e.g., { openai: "max_completion_tokens" }) */
158
+ knownAs: Record<string, string>;
159
+ }
160
+ /**
161
+ * Specification for the load()/load_from_value() static method.
162
+ * The emitter generates per-property deserialization based on field categories.
163
+ */
164
+ export interface LoadDecl {
165
+ /** Coercion checks applied before dict validation (isinstance checks) */
166
+ coercions: CoercionDecl[];
167
+ /** Per-property load assignments, ordered by field order */
168
+ assignments: LoadAssignment[];
169
+ /** Whether this type dispatches to polymorphic subtypes */
170
+ hasPolymorphicDispatch: boolean;
171
+ /** Whether LoadContext hooks are applied (process_input, process_output) */
172
+ hasContextHooks: boolean;
173
+ }
174
+ /**
175
+ * A coercion check: if the input matches a scalar type, transform it.
176
+ *
177
+ * Emitters use `assignments` for direct property setting (no intermediate dict).
178
+ */
179
+ export interface CoercionDecl {
180
+ /** Scalar type name from TypeSpec (e.g., "string", "boolean", "int64") */
181
+ scalarType: string;
182
+ /** Structured assignments — each property to set on the new instance */
183
+ assignments: CoercionAssignment[];
184
+ /**
185
+ * True when the coercion involves a dynamic discriminator value on a
186
+ * type with child variants. The emitter must call the dispatch method
187
+ * (e.g. `load_kind()`) instead of constructing the instance directly.
188
+ */
189
+ needsDispatch: boolean;
190
+ }
191
+ /**
192
+ * A single field assignment within a coercion.
193
+ */
194
+ export interface CoercionAssignment {
195
+ /** Property name (camelCase, as declared in TypeSpec) */
196
+ fieldName: string;
197
+ /** True when the value comes from the scalar input data */
198
+ isInput: boolean;
199
+ /** Literal string value when `isInput` is false */
200
+ literalValue?: string;
201
+ }
202
+ /**
203
+ * A single property load assignment.
204
+ * The category determines the deserialization pattern used by each language emitter.
205
+ */
206
+ export interface LoadAssignment {
207
+ /** Original property name (dict key, camelCase) */
208
+ sourceName: string;
209
+ /** Field to assign to (same as sourceName — emitters apply their own casing) */
210
+ fieldName: string;
211
+ /** Category determines the load pattern */
212
+ category: PropertyCategory;
213
+ /** Whether the field is optional */
214
+ isOptional: boolean;
215
+ /** Parent type name (needed for calling collection helpers like Parent.load_items) */
216
+ parentTypeName: string;
217
+ /** Enum type name (if this field references a named enum) */
218
+ enumName: string | null;
219
+ /** Allowed values for enum fields */
220
+ allowedValues: string[];
221
+ /** Default value (for fallback on missing/invalid data) */
222
+ defaultValue: string | number | boolean | null;
223
+ /** Whether the enum is open (accepts arbitrary string values) */
224
+ isOpenEnum: boolean;
225
+ }
226
+ /**
227
+ * Specification for the save() instance method.
228
+ */
229
+ export interface SaveDecl {
230
+ /** Per-property save assignments */
231
+ assignments: SaveAssignment[];
232
+ /** Whether to call super().save() first (has a base class) */
233
+ hasBase: boolean;
234
+ /** Whether SaveContext hooks are applied (process_object, process_dict) */
235
+ hasContextHooks: boolean;
236
+ }
237
+ /**
238
+ * A single property save assignment.
239
+ */
240
+ export interface SaveAssignment {
241
+ /** Property name (dict key to write to, camelCase) */
242
+ targetName: string;
243
+ /** Field name to read from (same as targetName — emitters apply their own casing) */
244
+ fieldName: string;
245
+ /** Category determines the serialization pattern */
246
+ category: PropertyCategory;
247
+ /** Whether the field is optional (skip if null/None/nil) */
248
+ isOptional: boolean;
249
+ /** Parent type name (for collection save helpers) */
250
+ parentTypeName: string;
251
+ /** Enum type name (if this field references a named enum) */
252
+ enumName: string | null;
253
+ /** Whether the enum is open (accepts arbitrary string values) */
254
+ isOpenEnum: boolean;
255
+ }
256
+ /**
257
+ * Specification for discriminator-based polymorphic dispatch.
258
+ * Generated as load_kind() in Python, loadKind() in TS, switch in C#, etc.
259
+ */
260
+ export interface PolymorphicDispatchDecl {
261
+ /** Discriminator field name (e.g., "kind") */
262
+ discriminatorField: string;
263
+ /** Concrete variant types with their discriminator values */
264
+ variants: PolymorphicVariant[];
265
+ /** Default/fallback type (wildcard or self-reference for non-abstract bases) */
266
+ defaultVariant: PolymorphicDefault | null;
267
+ /** Whether the base type is abstract (affects error handling on unknown values) */
268
+ isAbstract: boolean;
269
+ }
270
+ /**
271
+ * A concrete polymorphic variant (a child type with a known discriminator value).
272
+ */
273
+ export interface PolymorphicVariant {
274
+ /** Discriminator value that selects this variant (e.g., "text", "function") */
275
+ value: string;
276
+ /** Type to construct when this variant is matched */
277
+ typeName: TypeName;
278
+ }
279
+ /**
280
+ * Default/fallback for polymorphic dispatch.
281
+ */
282
+ export interface PolymorphicDefault {
283
+ /** The fallback type */
284
+ typeName: TypeName;
285
+ /** Whether this is a self-reference (base type falling back to itself — avoid infinite recursion) */
286
+ isSelfReference: boolean;
287
+ }
288
+ /**
289
+ * Specification for collection helper methods.
290
+ * Generated for properties that are collections of complex types
291
+ * (e.g., list[Tool], Vec<Property>).
292
+ *
293
+ * These handle the dict↔array format conversion:
294
+ * - Array format: [{ name: "a", kind: "b" }, ...]
295
+ * - Dict/object format: { "a": { kind: "b" }, ... }
296
+ */
297
+ export interface CollectionHelperDecl {
298
+ /** Property name (used for method naming: load_<name>, save_<name>) */
299
+ propertyName: string;
300
+ /** Element type name (the type being loaded/saved) */
301
+ elementTypeName: TypeName;
302
+ /** Field names on the element type (excluding "name" — used for shorthand detection) */
303
+ innerFields: string[];
304
+ /** Whether the element type has a "name" property (enables dict format) */
305
+ hasNameProperty: boolean;
306
+ }
307
+ /**
308
+ * A factory method declaration.
309
+ * The body is a pre-resolved Expr from the expression IR — emitters
310
+ * visit it with their ExprVisitor to produce language-specific code.
311
+ */
312
+ export interface FactoryDecl {
313
+ /** Original factory name from @factory decorator */
314
+ name: string;
315
+ /** Parameter name → type string mapping */
316
+ params: Record<string, string>;
317
+ /** Pre-resolved expression tree for the factory body */
318
+ body: Expr;
319
+ }
320
+ /**
321
+ * A method stub to be implemented in an extension module.
322
+ * Generated as comments/trait stubs pointing users to implement these.
323
+ * For protocol types, generates full interface method signatures.
324
+ */
325
+ export interface MethodStubDecl {
326
+ /** Method name */
327
+ name: string;
328
+ /** Return type as a string */
329
+ returns: string;
330
+ /** Human-readable description */
331
+ description: string;
332
+ /** Method parameters as ordered map of name → type string */
333
+ params: Record<string, string>;
334
+ /** Whether this method is optional (has a default implementation) */
335
+ optional: boolean;
336
+ /** Whether this method is synchronous (not wrapped in async/Promise/Task) */
337
+ sync: boolean;
338
+ }
339
+ /**
340
+ * Specification for the toWire(provider) method.
341
+ * Generated when at least one field on a type has knownAs mappings.
342
+ * Maps camelCase field names to provider-specific wire names.
343
+ */
344
+ export interface WireDecl {
345
+ /** All known provider identifiers (e.g., ["openai", "anthropic"]) */
346
+ providers: string[];
347
+ /** Per-field wire name mappings */
348
+ mappings: WireFieldMapping[];
349
+ }
350
+ /**
351
+ * A single field's wire name mappings across providers.
352
+ */
353
+ export interface WireFieldMapping {
354
+ /** Original field name (camelCase) */
355
+ fieldName: string;
356
+ /** Category of the field (for serialization) */
357
+ category: PropertyCategory;
358
+ /** Whether the field is optional */
359
+ isOptional: boolean;
360
+ /** Parent type name (for collection helpers) */
361
+ parentTypeName: string;
362
+ /** Provider → wire field name map */
363
+ wireNames: Record<string, string>;
364
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Declaration IR — Type-level code generation for the emitter.
3
+ *
4
+ * This module defines the "declaration" IR that replaces Nunjucks templates.
5
+ * Where the Expression IR (expansion.ts) handles factory/coercion bodies,
6
+ * the Declaration IR handles entire type definitions: structs, fields,
7
+ * load/save methods, polymorphic dispatch, collection helpers, and factories.
8
+ *
9
+ * Architecture:
10
+ * TypeNode graph → lowerFile() → FileDecl → emitPythonFile() → .py code
11
+ * → emitRustFile() → .rs code
12
+ * → emitTypeScriptFile() → .ts code
13
+ * → emitCSharpFile() → .cs code
14
+ * → emitGoFile() → .go code
15
+ *
16
+ * The lowering pass (lower.ts) converts the TypeNode graph into FileDecl trees.
17
+ * Per-language emitter functions walk the FileDecl tree to produce code.
18
+ *
19
+ * Key design principle: PropertyCategory is the fundamental 5-way classification
20
+ * that drives ALL per-property code generation across all languages.
21
+ */
22
+ export {};
23
+ //# sourceMappingURL=declarations.js.map
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Expression IR — Type-directed lowering for the emitter.
3
+ *
4
+ * This module implements the "lowering" pass of the transpiler:
5
+ * given an untyped data literal (from @factory sets or @coerce expansion)
6
+ * and a target type (TypeNode/PropertyNode), produce a typed Expr tree.
7
+ *
8
+ * The Expr tree is language-agnostic. Per-language visitors in render-expr.ts
9
+ * walk it to produce target language code.
10
+ *
11
+ * Architecture (following TypeScript/Roslyn/Babel pattern):
12
+ * Data literal + Type graph → resolve() → Expr tree → visit() → code string
13
+ */
14
+ import { TypeNode, TypeName } from "./ast.js";
15
+ /** A literal string value. */
16
+ export interface StringLiteral {
17
+ kind: "string";
18
+ value: string;
19
+ }
20
+ /** A literal number value. */
21
+ export interface NumberLiteral {
22
+ kind: "number";
23
+ value: number;
24
+ }
25
+ /** A literal boolean value. */
26
+ export interface BooleanLiteral {
27
+ kind: "boolean";
28
+ value: boolean;
29
+ }
30
+ /** A null/None/nil value. */
31
+ export interface NullLiteral {
32
+ kind: "null";
33
+ }
34
+ /** Reference to a factory/coercion parameter (substituted at runtime). */
35
+ export interface ParamRef {
36
+ kind: "param";
37
+ name: string;
38
+ paramType: string;
39
+ }
40
+ /** Direct construction of a non-polymorphic type. */
41
+ export interface Construct {
42
+ kind: "construct";
43
+ typeName: TypeName;
44
+ fields: FieldAssignment[];
45
+ }
46
+ /**
47
+ * Construction of a discriminated union variant.
48
+ * The base type has a discriminator field; we're constructing a specific child.
49
+ */
50
+ export interface VariantConstruct {
51
+ kind: "variant";
52
+ baseTypeName: TypeName;
53
+ discriminator: string;
54
+ discriminatorValue: string;
55
+ variantTypeName: TypeName;
56
+ fields: FieldAssignment[];
57
+ }
58
+ /** An array/list/vector literal. */
59
+ export interface ArrayLiteral {
60
+ kind: "array";
61
+ elementTypeName: TypeName;
62
+ items: Expr[];
63
+ }
64
+ /** A dictionary/map literal. */
65
+ export interface DictLiteral {
66
+ kind: "dict";
67
+ entries: {
68
+ key: string;
69
+ value: Expr;
70
+ }[];
71
+ }
72
+ /**
73
+ * A field read from a source object. Used in wire format mapping
74
+ * to read fields from core types (e.g., `opts.maxOutputTokens`).
75
+ */
76
+ export interface FieldRead {
77
+ kind: "field_read";
78
+ /** Source object/variable name (e.g., "opts") */
79
+ objectName: string;
80
+ /** Field name on the source object (e.g., "maxOutputTokens") */
81
+ fieldName: string;
82
+ /** Type of the field (e.g., "int32", "string") */
83
+ fieldType: string;
84
+ /** Whether the field is optional on the source object */
85
+ isOptional: boolean;
86
+ }
87
+ /** A field assignment within a Construct or VariantConstruct. */
88
+ export interface FieldAssignment {
89
+ /** Original property name from TypeSpec (camelCase). */
90
+ propertyName: string;
91
+ value: Expr;
92
+ /** Whether the target property is optional (emitters may need wrapping, e.g., Some(), null check) */
93
+ isOptional: boolean;
94
+ }
95
+ /** The Expression IR — a tagged union with exhaustive pattern matching. */
96
+ export type Expr = StringLiteral | NumberLiteral | BooleanLiteral | NullLiteral | ParamRef | Construct | VariantConstruct | ArrayLiteral | DictLiteral | FieldRead;
97
+ /**
98
+ * Recursively collect all TypeName references from an Expr tree.
99
+ * Used by emitters to determine which additional types need importing
100
+ * when factory/coercion expressions reference types from other modules.
101
+ */
102
+ export declare function collectExprTypeRefs(expr: Expr): TypeName[];
103
+ /**
104
+ * Registry of TypeNodes by name, enabling the resolver to look up types
105
+ * when processing nested objects and discriminated unions.
106
+ *
107
+ * Built from the emitter's type graph (TypeNode tree + enumerateTypes).
108
+ */
109
+ export declare class TypeRegistry {
110
+ private types;
111
+ /** Register a type by its simple name. */
112
+ register(node: TypeNode): void;
113
+ /** Look up a type by simple name. Returns undefined if not found. */
114
+ get(name: string): TypeNode | undefined;
115
+ /** Build a registry from a root TypeNode by walking all reachable types. */
116
+ static fromTypeGraph(roots: TypeNode[]): TypeRegistry;
117
+ }
118
+ /**
119
+ * Resolve a @factory decorator into a typed Expr tree.
120
+ *
121
+ * @param sets - Field assignments from the decorator (e.g., { allowed: true })
122
+ * @param params - Parameter declarations (e.g., { reason: "string" })
123
+ * @param targetType - The TypeNode this factory constructs
124
+ * @param registry - Type registry for resolving nested types
125
+ * @returns A Construct expression representing the factory body
126
+ */
127
+ export declare function resolveFactoryExpr(sets: Record<string, unknown>, params: Record<string, string>, targetType: TypeNode, registry: TypeRegistry): Construct;
128
+ /**
129
+ * Resolve a @coerce decorator into a typed Expr tree.
130
+ *
131
+ * A coercion is essentially a factory with a single implicit parameter named "value".
132
+ * The expansion dict maps property names to values, where "{value}" is the parameter ref.
133
+ *
134
+ * @param expansion - The expansion dict (e.g., { id: "{value}" })
135
+ * @param scalarType - The scalar type string (e.g., "string")
136
+ * @param targetType - The TypeNode this coercion constructs
137
+ * @param registry - Type registry for resolving nested types
138
+ * @returns A Construct expression representing the coercion expansion
139
+ */
140
+ export declare function resolveCoerceExpr(expansion: Record<string, unknown>, scalarType: string, targetType: TypeNode, registry: TypeRegistry, paramName?: string): Construct;