gen-typescript-from-tolk-dev 0.1.0 → 0.2.1

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 (50) hide show
  1. package/README.md +33 -29
  2. package/dist/abi-types.d.ts +169 -0
  3. package/dist/abi-types.js +8 -0
  4. package/dist/abi.d.ts +54 -0
  5. package/dist/abi.js +13 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +83 -0
  8. package/dist/codegen-ctx.d.ts +66 -0
  9. package/dist/codegen-ctx.js +108 -0
  10. package/dist/emit-field-defs.d.ts +5 -0
  11. package/dist/emit-field-defs.js +61 -0
  12. package/dist/emit-pack-unpack.d.ts +9 -0
  13. package/dist/emit-pack-unpack.js +296 -0
  14. package/dist/emit-stack-rw.d.ts +4 -0
  15. package/dist/emit-stack-rw.js +232 -0
  16. package/dist/emit-ts-types.d.ts +6 -0
  17. package/dist/emit-ts-types.js +74 -0
  18. package/dist/formatting.d.ts +15 -0
  19. package/{src/formatting.ts → dist/formatting.js} +26 -28
  20. package/dist/generate-ts-wrappers.d.ts +7 -0
  21. package/dist/generate-ts-wrappers.js +444 -0
  22. package/dist/index.d.ts +4 -0
  23. package/dist/index.js +11 -0
  24. package/dist/out-template.generated.d.ts +1 -0
  25. package/dist/out-template.generated.js +6 -0
  26. package/dist/types-kernel.d.ts +10 -0
  27. package/dist/types-kernel.js +212 -0
  28. package/dist/unsupported-errors.d.ts +28 -0
  29. package/{src/unsupported-errors.ts → dist/unsupported-errors.js} +33 -39
  30. package/package.json +56 -30
  31. package/bin/generator.js +0 -15
  32. package/src/abi-types.ts +0 -157
  33. package/src/abi.ts +0 -132
  34. package/src/cli-generate-from-abi-json.ts +0 -21
  35. package/src/codegen-ctx.ts +0 -115
  36. package/src/dynamic-ctx.ts +0 -55
  37. package/src/dynamic-debug-print.ts +0 -191
  38. package/src/dynamic-get-methods.ts +0 -454
  39. package/src/dynamic-serialization.ts +0 -430
  40. package/src/dynamic-validation.ts +0 -55
  41. package/src/emit-field-defs.ts +0 -60
  42. package/src/emit-pack-unpack.ts +0 -280
  43. package/src/emit-stack-rw.ts +0 -239
  44. package/src/emit-ts-types.ts +0 -66
  45. package/src/generate-from-abi-json.ts +0 -22
  46. package/src/generate-ts-wrappers.ts +0 -477
  47. package/src/out-template.ts +0 -514
  48. package/src/tolk-to-abi.ts +0 -5
  49. package/src/types-kernel.ts +0 -215
  50. package/tsconfig.json +0 -13
@@ -0,0 +1,296 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.emitLoadExpr = emitLoadExpr;
4
+ exports.emitLoadCallback = emitLoadCallback;
5
+ exports.emitStoreStatement = emitStoreStatement;
6
+ exports.emitStoreCallback = emitStoreCallback;
7
+ exports.emitMakeCellFromExpr = emitMakeCellFromExpr;
8
+ exports.emitCallToCreateMethodExpr = emitCallToCreateMethodExpr;
9
+ exports.emitDictKVSerializers = emitDictKVSerializers;
10
+ const codegen_ctx_1 = require("./codegen-ctx");
11
+ const emit_ts_types_1 = require("./emit-ts-types");
12
+ const formatting_1 = require("./formatting");
13
+ const unsupported_errors_1 = require("./unsupported-errors");
14
+ const types_kernel_1 = require("./types-kernel");
15
+ // Emit a TS "load {ty} from slice `s`" expression.
16
+ // Parameter `fieldPath` is used for error messages only: e.g. when an input opcode is incorrect,
17
+ // the fired Error will contain struct/field name.
18
+ function emitLoadExpr(ctx, fieldPath, ty) {
19
+ switch (ty.kind) {
20
+ case 'int':
21
+ case 'builder':
22
+ case 'slice':
23
+ case 'unknown':
24
+ case 'callable': {
25
+ let hint = ty.kind === 'int' ? ' (not int32/uint64/etc.)' :
26
+ ty.kind === 'builder' || ty.kind === 'slice' ? ' (it can be used for writing only)' :
27
+ '';
28
+ throw new unsupported_errors_1.CantGeneratePackUnpack(`'${fieldPath}' is '${(0, types_kernel_1.renderTy)(ty)}'${hint}`);
29
+ }
30
+ case 'intN': return `s.loadIntBig(${ty.n})`;
31
+ case 'uintN': return `s.loadUintBig(${ty.n})`;
32
+ case 'varintN': return `s.loadVarIntBig(${Math.log2(ty.n)})`;
33
+ case 'varuintN': return `s.loadVarUintBig(${Math.log2(ty.n)})`;
34
+ case 'coins': return `s.loadCoins()`;
35
+ case 'bool': return `s.loadBoolean()`;
36
+ case 'cell': return `s.loadRef()`;
37
+ case 'string': return `s.loadStringRefTail()`;
38
+ case 'remaining': return `${codegen_ctx_1.RUNTIME.loadTolkRemaining}(s)`;
39
+ case 'address': return `s.loadAddress()`;
40
+ case 'addressOpt': return `s.loadMaybeAddress()`;
41
+ case 'addressExt': return `s.loadExternalAddress()`;
42
+ case 'addressAny': return `${codegen_ctx_1.RUNTIME.loadTolkAddressAny}(s)`;
43
+ case 'bitsN': return `${codegen_ctx_1.RUNTIME.loadTolkBitsN}(s, ${ty.n})`;
44
+ case 'nullLiteral': return `null`;
45
+ case 'void': return `void 0`;
46
+ case 'nullable': return `s.loadBoolean() ? ${emitLoadExpr(ctx, fieldPath, ty.inner)} : null`;
47
+ case 'cellOf': return `${codegen_ctx_1.RUNTIME.loadCellRef}<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(s, ${emitLoadCallback(ctx, fieldPath, ty.inner)})`;
48
+ case 'arrayOf': return `${codegen_ctx_1.RUNTIME.loadArrayOf}<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(s, ${emitLoadCallback(ctx, fieldPath + '[ith]', ty.inner)})`;
49
+ case 'lispListOf': return `${codegen_ctx_1.RUNTIME.loadLispListOf}<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(s, ${emitLoadCallback(ctx, fieldPath + '[ith]', ty.inner)})`;
50
+ case 'tensor': return `[${ty.items.map((item, i) => emitLoadExpr(ctx, `${fieldPath}[${i}]`, item)).join(', ')}]`;
51
+ case 'shapedTuple': return `[${ty.items.map((item, i) => emitLoadExpr(ctx, `${fieldPath}[${i}]`, item)).join(', ')}]`;
52
+ case 'mapKV': return `c.Dictionary.load<${(0, emit_ts_types_1.emitDictKVTypeArgs)(ctx, ty.k, ty.v)}>(${emitDictKVSerializers(ctx, fieldPath, ty.k, ty.v)}, s)`;
53
+ case 'EnumRef': return `${ty.enum_name}.fromSlice(s)`;
54
+ case 'StructRef': {
55
+ if (ty.type_args) {
56
+ const cb = ty.type_args.map((ta) => emitLoadCallback(ctx, fieldPath, ta)).join(', ');
57
+ return `${(0, formatting_1.safeJsIdent)(ty.struct_name)}.fromSlice<${ty.type_args.map((ta) => (0, emit_ts_types_1.emitTsType)(ctx, ta)).join(', ')}>(s, ${cb})`;
58
+ }
59
+ return `${(0, formatting_1.safeJsIdent)(ty.struct_name)}.fromSlice(s)`;
60
+ }
61
+ case 'AliasRef': {
62
+ if (ty.type_args) {
63
+ const cb = ty.type_args.map((ta) => emitLoadCallback(ctx, fieldPath, ta)).join(', ');
64
+ return `${(0, formatting_1.safeJsIdent)(ty.alias_name)}.fromSlice<${ty.type_args.map((ta) => (0, emit_ts_types_1.emitTsType)(ctx, ta)).join(', ')}>(s, ${cb})`;
65
+ }
66
+ return `${(0, formatting_1.safeJsIdent)(ty.alias_name)}.fromSlice(s)`;
67
+ }
68
+ case 'genericT': return `loadFn_${ty.name_t}(s)`;
69
+ case 'union': {
70
+ const variants = (0, types_kernel_1.createLabelsForUnion)(ctx.symbols, ty.variants);
71
+ const isEither01 = variants.length === 2 && variants[0].prefix_str === '0b0' && variants[1].prefix_str === '0b1';
72
+ if (isEither01) {
73
+ const l = (0, emit_ts_types_1.emitUnionLabelAndValue)(variants[0], emitLoadExpr(ctx, fieldPath, variants[0].variant_ty));
74
+ const r = (0, emit_ts_types_1.emitUnionLabelAndValue)(variants[1], emitLoadExpr(ctx, fieldPath, variants[1].variant_ty));
75
+ return `s.loadBoolean() ? ${r} : ${l}`;
76
+ }
77
+ let buf = new formatting_1.OutBuf();
78
+ for (let v of variants) {
79
+ const checkFn = v.is_prefix_implicit ? codegen_ctx_1.RUNTIME.lookupPrefixAndEat : codegen_ctx_1.RUNTIME.lookupPrefix;
80
+ const body = (0, emit_ts_types_1.emitUnionLabelAndValue)(v, emitLoadExpr(ctx, fieldPath, v.variant_ty));
81
+ buf.push(`${checkFn}(s, ${v.prefix_str}, ${v.prefix_len}) ? ${body} :`);
82
+ if (v.is_prefix_implicit) {
83
+ ctx.has_implicitUnionPrefix = true;
84
+ }
85
+ if (v.prefix_str === variants[0].prefix_str) {
86
+ buf.indent();
87
+ }
88
+ }
89
+ buf.push(`${codegen_ctx_1.RUNTIME.throwNonePrefixMatch}('${fieldPath}')`);
90
+ return buf.toString();
91
+ }
92
+ }
93
+ }
94
+ // Emit a TS "load {ty} from slice `s`" callback (not expression).
95
+ // Callbacks are passed for generics (user-defined generic types and built-ins),
96
+ // e.g., `loadCellRef<T>(s, {callbackForT})`.
97
+ // We could just emit `(s) => loadExprForT(s)`, but to produce less boilerplate, shorten common cases:
98
+ // not `(s) => SomeStruct.fromSlice(s)` but `SomeStruct.fromSlice` as a valid callback.
99
+ function emitLoadCallback(ctx, fieldPath, ty) {
100
+ if (ty.kind === 'addressAny')
101
+ return codegen_ctx_1.RUNTIME.loadTolkAddressAny;
102
+ if (ty.kind === 'remaining')
103
+ return codegen_ctx_1.RUNTIME.loadTolkRemaining;
104
+ if (ty.kind === 'EnumRef')
105
+ return `${ty.enum_name}.fromSlice`;
106
+ if (ty.kind === 'genericT')
107
+ return `loadFn_${ty.name_t}`;
108
+ if (ty.kind === 'StructRef' && !ty.type_args)
109
+ return `${(0, formatting_1.safeJsIdent)(ty.struct_name)}.fromSlice`;
110
+ if (ty.kind === 'AliasRef' && !ty.type_args)
111
+ return `${(0, formatting_1.safeJsIdent)(ty.alias_name)}.fromSlice`;
112
+ return formatting_1.OutBuf.onNewLine(`(s) => ${emitLoadExpr(ctx, fieldPath, ty)}`);
113
+ }
114
+ // Emit a TS "store {expr of type ty} into builder `b`" statement.
115
+ // Parameter `tsExpr` is a valid expression: "self.field", "v" (inside a callback), and other.
116
+ function emitStoreStatement(ctx, tsExpr, ty) {
117
+ switch (ty.kind) {
118
+ case 'int':
119
+ case 'unknown':
120
+ case 'nullLiteral':
121
+ case 'callable': {
122
+ let hint = ty.kind === 'int' ? ' (not int32/uint64/etc.)' : '';
123
+ throw new unsupported_errors_1.CantGeneratePackUnpack(`'${tsExpr}' is '${(0, types_kernel_1.renderTy)(ty)}'${hint}`);
124
+ }
125
+ case 'intN': return `b.storeInt(${tsExpr}, ${ty.n});`;
126
+ case 'uintN': return `b.storeUint(${tsExpr}, ${ty.n});`;
127
+ case 'varintN': return `b.storeVarInt(${tsExpr}, ${Math.log2(ty.n)});`;
128
+ case 'varuintN': return `b.storeVarUint(${tsExpr}, ${Math.log2(ty.n)});`;
129
+ case 'coins': return `b.storeCoins(${tsExpr});`;
130
+ case 'bool': return `b.storeBit(${tsExpr});`;
131
+ case 'cell': return `b.storeRef(${tsExpr});`;
132
+ case 'builder': return `b.storeBuilder(${tsExpr});`;
133
+ case 'slice': return `b.storeSlice(${tsExpr});`;
134
+ case 'string': return `b.storeStringRefTail(${tsExpr});`;
135
+ case 'remaining': return `${codegen_ctx_1.RUNTIME.storeTolkRemaining}(${tsExpr}, b);`;
136
+ case 'address': return `b.storeAddress(${tsExpr});`;
137
+ case 'addressOpt': return `b.storeAddress(${tsExpr});`;
138
+ case 'addressExt': return `b.storeAddress(${tsExpr});`;
139
+ case 'addressAny': return `${codegen_ctx_1.RUNTIME.storeTolkAddressAny}(${tsExpr}, b);`;
140
+ case 'bitsN': return `${codegen_ctx_1.RUNTIME.storeTolkBitsN}(${tsExpr}, ${ty.n}, b);`;
141
+ case 'void': return ``;
142
+ case 'nullable': return `${codegen_ctx_1.RUNTIME.storeTolkNullable}<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(${tsExpr}, b, ${emitStoreCallback(ctx, ty.inner)});`;
143
+ case 'cellOf': return `${codegen_ctx_1.RUNTIME.storeCellRef}<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(${tsExpr}, b, ${emitStoreCallback(ctx, ty.inner)});`;
144
+ case 'arrayOf': return `${codegen_ctx_1.RUNTIME.storeArrayOf}<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(${tsExpr}, b, ${emitStoreCallback(ctx, ty.inner)});`;
145
+ case 'lispListOf': return `${codegen_ctx_1.RUNTIME.storeLispListOf}<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(${tsExpr}, b, ${emitStoreCallback(ctx, ty.inner)});`;
146
+ case 'tensor': return ty.items.length ? ty.items.map((_, i) => emitStoreStatement(ctx, `${tsExpr}[${i}]`, ty.items[i])).join('\n') : `{}`;
147
+ case 'shapedTuple': return ty.items.length ? ty.items.map((_, i) => emitStoreStatement(ctx, `${tsExpr}[${i}]`, ty.items[i])).join('\n') : `{}`;
148
+ case 'mapKV': return `b.storeDict<${(0, emit_ts_types_1.emitDictKVTypeArgs)(ctx, ty.k, ty.v)}>(${tsExpr}, ${emitDictKVSerializers(ctx, tsExpr, ty.k, ty.v)});`;
149
+ case 'EnumRef': return `${ty.enum_name}.store(${tsExpr}, b);`;
150
+ case 'StructRef': {
151
+ if (ty.type_args) {
152
+ const cb = ty.type_args.map(ta => emitStoreCallback(ctx, ta)).join(', ');
153
+ return `${(0, formatting_1.safeJsIdent)(ty.struct_name)}.store<${ty.type_args.map(ta => (0, emit_ts_types_1.emitTsType)(ctx, ta)).join(', ')}>(${tsExpr}, b, ${cb});`;
154
+ }
155
+ return `${(0, formatting_1.safeJsIdent)(ty.struct_name)}.store(${tsExpr}, b);`;
156
+ }
157
+ case 'AliasRef': {
158
+ if (ty.type_args) {
159
+ const cb = ty.type_args.map(ta => emitStoreCallback(ctx, ta)).join(', ');
160
+ return `${(0, formatting_1.safeJsIdent)(ty.alias_name)}.store<${ty.type_args.map(ta => (0, emit_ts_types_1.emitTsType)(ctx, ta)).join(', ')}>(${tsExpr}, b, ${cb});`;
161
+ }
162
+ return `${(0, formatting_1.safeJsIdent)(ty.alias_name)}.store(${tsExpr}, b);`;
163
+ }
164
+ case 'genericT': return `storeFn_${ty.name_t}(${tsExpr}, b);`;
165
+ case 'union': {
166
+ const buf = new formatting_1.OutBuf();
167
+ const variants = (0, types_kernel_1.createLabelsForUnion)(ctx.symbols, ty.variants);
168
+ const hasNull = variants.find(v => v.variant_ty.kind === 'nullLiteral');
169
+ if (hasNull) {
170
+ buf.push(`if (${tsExpr} === null) {`);
171
+ buf.push(`b.storeUint(${hasNull.prefix_str}, ${hasNull.prefix_len});`);
172
+ buf.push(`} else switch (${tsExpr}.$) {`);
173
+ }
174
+ else {
175
+ buf.push(`switch (${tsExpr}.$) {`);
176
+ }
177
+ for (let v of variants) {
178
+ if (v.variant_ty.kind === 'nullLiteral')
179
+ continue;
180
+ buf.push(`case '${v.labelStr}':`).indent();
181
+ if (v.is_prefix_implicit) {
182
+ buf.push(`b.storeUint(${v.prefix_str}, ${v.prefix_len});`);
183
+ }
184
+ buf.push(emitStoreStatement(ctx, v.hasValueField ? `${tsExpr}.value` : tsExpr, v.variant_ty));
185
+ buf.push('break;').outdent();
186
+ }
187
+ buf.push('}');
188
+ return buf.toString();
189
+ }
190
+ }
191
+ }
192
+ // Emit a TS "store {expr of type ty} into builder `b`" callback (not expression).
193
+ // Callbacks are passed for generics (user-defined generic types and built-ins),
194
+ // e.g., `storeTolkNullable<T>(s, {callbackForT})`.
195
+ function emitStoreCallback(ctx, ty) {
196
+ if (ty.kind === 'addressAny')
197
+ return codegen_ctx_1.RUNTIME.storeTolkAddressAny;
198
+ if (ty.kind === 'remaining')
199
+ return codegen_ctx_1.RUNTIME.storeTolkRemaining;
200
+ if (ty.kind === 'EnumRef')
201
+ return `${ty.enum_name}.store`;
202
+ if (ty.kind === 'genericT')
203
+ return `storeFn_${ty.name_t}`;
204
+ if (ty.kind === 'StructRef' && !ty.type_args)
205
+ return `${(0, formatting_1.safeJsIdent)(ty.struct_name)}.store`;
206
+ if (ty.kind === 'AliasRef' && !ty.type_args)
207
+ return `${(0, formatting_1.safeJsIdent)(ty.alias_name)}.store`;
208
+ // for simple statements, drop trailing `;` and use it as an expression:
209
+ // not `(v,b) => { b.storeInt(v, 8); }` but `(v,b) => b.storeInt(v, 8)`
210
+ let stmt = emitStoreStatement(ctx, 'v', ty);
211
+ if (stmt.indexOf(';') !== stmt.length - 1 || stmt.includes('\n') || stmt.includes('{')) {
212
+ stmt = '{ ' + stmt + ' }';
213
+ }
214
+ else if (stmt[stmt.length - 1] === ';') {
215
+ stmt = stmt.substring(0, stmt.length - 1);
216
+ }
217
+ return formatting_1.OutBuf.onNewLine(`(v,b) => ${stmt}`);
218
+ }
219
+ // Emit a TS "make a cell from {expr}" expression.
220
+ // It's essentially beginCell + call storing callback + endCell.
221
+ // Parameter `tsExpr` is a valid expression: "self.field", "v" (inside a callback), and other.
222
+ function emitMakeCellFromExpr(ctx, tsExpr, ty, disableShortHand = false) {
223
+ if (disableShortHand) {
224
+ return `${codegen_ctx_1.RUNTIME.makeCellFrom}<${(0, emit_ts_types_1.emitTsType)(ctx, ty)}>(${tsExpr}, ${emitStoreCallback(ctx, ty)})`;
225
+ }
226
+ switch (ty.kind) {
227
+ case 'EnumRef': {
228
+ return `${(0, formatting_1.safeJsIdent)(ty.enum_name)}.toCell(${tsExpr})`;
229
+ }
230
+ case 'StructRef': {
231
+ if (ty.type_args) {
232
+ const cb = ty.type_args.map(ta => emitStoreCallback(ctx, ta)).join(', ');
233
+ return `${(0, formatting_1.safeJsIdent)(ty.struct_name)}.toCell<${ty.type_args.map(ta => (0, emit_ts_types_1.emitTsType)(ctx, ta)).join(', ')}>(${tsExpr}, ${cb})`;
234
+ }
235
+ return `${(0, formatting_1.safeJsIdent)(ty.struct_name)}.toCell(${tsExpr})`;
236
+ }
237
+ case 'AliasRef': {
238
+ if (ty.type_args) {
239
+ const cb = ty.type_args.map(ta => emitStoreCallback(ctx, ta)).join(', ');
240
+ return `${(0, formatting_1.safeJsIdent)(ty.alias_name)}.toCell<${ty.type_args.map(ta => (0, emit_ts_types_1.emitTsType)(ctx, ta)).join(', ')}>(${tsExpr}, ${cb})`;
241
+ }
242
+ return `${(0, formatting_1.safeJsIdent)(ty.alias_name)}.toCell(${tsExpr})`;
243
+ }
244
+ default:
245
+ return emitMakeCellFromExpr(ctx, tsExpr, ty, true);
246
+ }
247
+ }
248
+ // Emit a TS "StructName.create({bodyArg})" expression.
249
+ // For instance, sendXXX and fromStorage methods accept struct fields and call create()
250
+ // in order to enrich passed fields with `$` tag and default values.
251
+ function emitCallToCreateMethodExpr(ctx, bodyArg, ty) {
252
+ if (ty.kind === 'StructRef') {
253
+ let structRef = ctx.symbols.getStruct(ty.struct_name);
254
+ if (structRef.fields.length === 0) {
255
+ bodyArg = ''; // create() is without arguments, body is an empty object
256
+ }
257
+ if (ty.type_args) {
258
+ return `${(0, formatting_1.safeJsIdent)(ty.struct_name)}.create<${ty.type_args.map(ta => (0, emit_ts_types_1.emitTsType)(ctx, ta)).join(', ')}>(${bodyArg})`;
259
+ }
260
+ return `${(0, formatting_1.safeJsIdent)(ty.struct_name)}.create(${bodyArg})`;
261
+ }
262
+ throw new Error(`can not emit create() call for ${ty.kind}`);
263
+ }
264
+ // Emit a key (de)serializer for c.Dictionary<K, V>.
265
+ // Only a strict subset of KeyT is allowed by the @ton/core library.
266
+ // For others, we can not generate wrappers at all (not only to/from cell, but even declarations).
267
+ function emitDictKeySerializer(ctx, fieldPath, tyK) {
268
+ if (tyK.kind === 'intN')
269
+ return `c.Dictionary.Keys.BigInt(${tyK.n})`;
270
+ if (tyK.kind === 'uintN')
271
+ return `c.Dictionary.Keys.BigUint(${tyK.n})`;
272
+ if (tyK.kind === 'address')
273
+ return `c.Dictionary.Keys.Address()`;
274
+ throw new unsupported_errors_1.NonStandardDictKey(`'${fieldPath}' is 'map<${(0, types_kernel_1.renderTy)(tyK)}, ...>': such a non-standard map key can not be handled by @ton/core library`);
275
+ }
276
+ // Emit a value (de)serializer for c.Dictionary<K, V>.
277
+ // Unlike keys, @ton/core allows arbitrary values (passing custom (de)serializers).
278
+ // For common cases, use a built-in one; for others, create a custom.
279
+ function emitDictValueSerializer(ctx, fieldPath, tyV) {
280
+ if (tyV.kind === 'intN')
281
+ return `c.Dictionary.Values.BigInt(${tyV.n})`;
282
+ if (tyV.kind === 'uintN')
283
+ return `c.Dictionary.Values.BigUint(${tyV.n})`;
284
+ if (tyV.kind === 'coins')
285
+ return `c.Dictionary.Values.BigVarUint(4)`;
286
+ if (tyV.kind === 'bool')
287
+ return `c.Dictionary.Values.Bool()`;
288
+ if (tyV.kind === 'cell')
289
+ return `c.Dictionary.Values.Cell()`;
290
+ ctx.has_customDictV = true;
291
+ return `${codegen_ctx_1.RUNTIME.createDictionaryValue}<${(0, emit_ts_types_1.emitTsType)(ctx, tyV)}>(${emitLoadCallback(ctx, fieldPath, tyV)}, ${emitStoreCallback(ctx, tyV)})`;
292
+ }
293
+ // Emit (de)serializers for c.Dictionary<K, V> (two arguments separated by a comma).
294
+ function emitDictKVSerializers(ctx, fieldPath, tyK, tyV) {
295
+ return emitDictKeySerializer(ctx, fieldPath, tyK) + ', ' + emitDictValueSerializer(ctx, fieldPath, tyV);
296
+ }
@@ -0,0 +1,4 @@
1
+ import type { Ty } from './abi-types';
2
+ import { CodegenCtx } from './codegen-ctx';
3
+ export declare function emitStackReadExpr(ctx: CodegenCtx, fieldPath: string, ty: Ty, unTupleIfW?: boolean): string;
4
+ export declare function emitStackWriteItems(ctx: CodegenCtx, tsExpr: string, ty: Ty, tupleIfW?: boolean): string[];
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.emitStackReadExpr = emitStackReadExpr;
4
+ exports.emitStackWriteItems = emitStackWriteItems;
5
+ const codegen_ctx_1 = require("./codegen-ctx");
6
+ const emit_ts_types_1 = require("./emit-ts-types");
7
+ const formatting_1 = require("./formatting");
8
+ const emit_pack_unpack_1 = require("./emit-pack-unpack");
9
+ const unsupported_errors_1 = require("./unsupported-errors");
10
+ const types_kernel_1 = require("./types-kernel");
11
+ // Emit a TS "read {ty} from a stack `r`" expression.
12
+ // Parameter `fieldPath` is used for error messages only.
13
+ // Used to read getters return value, since contract getters work via the stack, not serialization.
14
+ function emitStackReadExpr(ctx, fieldPath, ty, unTupleIfW = false) {
15
+ ctx.stackReadsUnknown || (ctx.stackReadsUnknown = ty.kind === 'unknown');
16
+ ctx.stackReadsArrayOf || (ctx.stackReadsArrayOf = ty.kind === 'arrayOf');
17
+ ctx.stackReadsLispListOf || (ctx.stackReadsLispListOf = ty.kind === 'lispListOf');
18
+ ctx.stackReadsSnakeString || (ctx.stackReadsSnakeString = ty.kind === 'string');
19
+ ctx.stackReadsTuple || (ctx.stackReadsTuple = ty.kind === 'arrayOf' || ty.kind === 'lispListOf' || ty.kind === 'shapedTuple');
20
+ ctx.stackReadsMapKV || (ctx.stackReadsMapKV = ty.kind === 'mapKV');
21
+ ctx.stackReadsBuilder || (ctx.stackReadsBuilder = ty.kind === 'builder');
22
+ ctx.stackReadsNullable || (ctx.stackReadsNullable = ty.kind === 'nullable');
23
+ ctx.stackReadsWideNullable || (ctx.stackReadsWideNullable = ty.kind === 'nullable' && ty.stack_type_id !== undefined);
24
+ ctx.stackReadsUnionType || (ctx.stackReadsUnionType = ty.kind === 'union');
25
+ ctx.stackReadsCellRef || (ctx.stackReadsCellRef = ty.kind === 'cellOf');
26
+ ctx.stackReadsNullLiteral || (ctx.stackReadsNullLiteral = ty.kind === 'nullLiteral');
27
+ if (unTupleIfW) { // inside `array<T>` or `[T, ...]`, if T is non-primitive, it's a sub-tuple
28
+ let wOnStack = (0, types_kernel_1.calcWidthOnStack)(ctx.symbols, ty);
29
+ if (wOnStack !== 1) {
30
+ return `r.readTuple<${(0, emit_ts_types_1.emitTsType)(ctx, ty)}>(${wOnStack}, ${emitStackReadCallback(ctx, fieldPath, ty, false)})`;
31
+ }
32
+ }
33
+ switch (ty.kind) {
34
+ case 'int':
35
+ case 'intN':
36
+ case 'uintN':
37
+ case 'varintN':
38
+ case 'varuintN':
39
+ case 'coins': return `r.readBigInt()`;
40
+ case 'bool': return `r.readBoolean()`;
41
+ case 'cell': return `r.readCell()`;
42
+ case 'builder': return `r.readBuilder()`;
43
+ case 'slice': return `r.readSlice()`;
44
+ case 'string': return `r.readSnakeString()`;
45
+ case 'remaining': return `r.readSlice()`;
46
+ case 'address': return `r.readSlice().loadAddress()`;
47
+ case 'addressOpt': return emitStackReadExpr(ctx, fieldPath, { kind: 'nullable', inner: { kind: 'address' } });
48
+ case 'addressExt': return `r.readSlice().loadExternalAddress()`;
49
+ case 'addressAny': return `${codegen_ctx_1.RUNTIME.loadTolkAddressAny}(r.readSlice())`;
50
+ case 'bitsN': return `r.readSlice()`;
51
+ case 'nullLiteral': return `r.readNullLiteral()`;
52
+ case 'callable': throw new unsupported_errors_1.NotSupportedTypeOnStack(ty, fieldPath);
53
+ case 'void': return `void 0`;
54
+ case 'unknown': return `r.readUnknown()`;
55
+ case 'nullable': {
56
+ if (ty.stack_type_id) {
57
+ return `r.readWideNullable<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(${ty.stack_width}, ${emitStackReadCallback(ctx, fieldPath, ty.inner, false)})`;
58
+ }
59
+ return `r.readNullable<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(${emitStackReadCallback(ctx, fieldPath, ty.inner, false)})`;
60
+ }
61
+ case 'cellOf': return `r.readCellRef<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(${(0, emit_pack_unpack_1.emitLoadCallback)(ctx, fieldPath + '.ref', ty.inner)})`;
62
+ case 'arrayOf': return `r.readArrayOf<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(${emitStackReadCallback(ctx, fieldPath, ty.inner, true)})`;
63
+ case 'lispListOf': return `r.readLispListOf<${(0, emit_ts_types_1.emitTsType)(ctx, ty.inner)}>(${emitStackReadCallback(ctx, fieldPath, ty.inner, true)})`;
64
+ case 'tensor': {
65
+ let buf = new formatting_1.OutBuf();
66
+ buf.push(`[`);
67
+ for (let i = 0; i < ty.items.length; ++i) {
68
+ buf.push(emitStackReadExpr(ctx, `${fieldPath}[${i}]`, ty.items[i]) + ',');
69
+ }
70
+ buf.push(']');
71
+ return buf.toString();
72
+ }
73
+ case 'shapedTuple': {
74
+ let buf = new formatting_1.OutBuf();
75
+ buf.push(`r.readTuple<${(0, emit_ts_types_1.emitTsType)(ctx, ty)}>(${ty.items.length}, (r) => [`);
76
+ for (let i = 0; i < ty.items.length; ++i) {
77
+ buf.push(emitStackReadExpr(ctx, `${fieldPath}[${i}]`, ty.items[i], true) + ',');
78
+ }
79
+ buf.push('])');
80
+ return buf.toString();
81
+ }
82
+ case 'mapKV': return `r.readDictionary<${(0, emit_ts_types_1.emitDictKVTypeArgs)(ctx, ty.k, ty.v)}>(${(0, emit_pack_unpack_1.emitDictKVSerializers)(ctx, fieldPath, ty.k, ty.v)})`;
83
+ case 'EnumRef': return `r.readBigInt()`;
84
+ case 'StructRef': {
85
+ const structRef = ctx.symbols.getStruct(ty.struct_name);
86
+ let buf = new formatting_1.OutBuf();
87
+ buf.push(`({`);
88
+ buf.push(`$: '${ty.struct_name}',`);
89
+ for (let f of structRef.fields) {
90
+ const fTy = ty.type_args ? (0, types_kernel_1.instantiateGenerics)(f.ty, structRef.type_params, ty.type_args) : f.ty;
91
+ buf.push(`${(0, formatting_1.safeFieldDecl)(f.name)}: ${emitStackReadExpr(ctx, `${fieldPath}.${f.name}`, fTy)},`);
92
+ }
93
+ buf.push(`})`);
94
+ return buf.toString();
95
+ }
96
+ case 'AliasRef': {
97
+ const aliasRef = ctx.symbols.getAlias(ty.alias_name);
98
+ const targetTy = ty.type_args ? (0, types_kernel_1.instantiateGenerics)(aliasRef.target_ty, aliasRef.type_params, ty.type_args) : aliasRef.target_ty;
99
+ return emitStackReadExpr(ctx, fieldPath, targetTy);
100
+ }
101
+ case 'genericT': throw new Error(`unexpected genericT=${ty.name_t} in '${fieldPath}'`);
102
+ case 'union': {
103
+ const variants = (0, types_kernel_1.createLabelsForUnion)(ctx.symbols, ty.variants);
104
+ let buf = new formatting_1.OutBuf();
105
+ buf.push(`r.readUnionType<${(0, emit_ts_types_1.emitTsType)(ctx, ty)}>(${ty.stack_width}, {`);
106
+ for (let v of variants) {
107
+ buf.push(`${v.stack_type_id}: [${v.stack_width}, ${v.hasValueField ? `'${v.labelStr}'` : 'null'}, ${emitStackReadCallback(ctx, `${fieldPath}#${v.stack_type_id}`, v.variant_ty, false)}],`);
108
+ }
109
+ buf.push(`})`);
110
+ return buf.toString();
111
+ }
112
+ }
113
+ }
114
+ // Emit a TS "read {ty} from a stack `r`" callback (not expression).
115
+ // Callbacks are passed for generics — for example, to read a nullable (when a stack slot is not null).
116
+ function emitStackReadCallback(ctx, fieldPath, ty, unTupleIfW) {
117
+ return formatting_1.OutBuf.onNewLine(`(r) => ${emitStackReadExpr(ctx, fieldPath, ty, unTupleIfW)}`);
118
+ }
119
+ // Emit a TS "write {expr of type ty} to a stack" expression compatible with @ton/core TupleItem.
120
+ // Used to pass getters arguments, since contract getters work via the stack, not serialization.
121
+ // Parameter `tsExpr` is a valid expression: "p1.field", "p2[0]", "ith" (inside a callback), and other.
122
+ function emitStackWriteItems(ctx, tsExpr, ty, tupleIfW = false) {
123
+ if (tupleIfW) { // inside `array<T>` or `[T, ...]`, if T is non-primitive, it's a sub-tuple
124
+ if ((0, types_kernel_1.calcWidthOnStack)(ctx.symbols, ty) === 1) {
125
+ return emitStackWriteItems(ctx, tsExpr, ty, false);
126
+ }
127
+ let buf = new formatting_1.OutBuf();
128
+ buf.push(`{ type: 'tuple', items: [`);
129
+ for (let line of emitStackWriteItems(ctx, tsExpr, ty, false)) {
130
+ buf.push(line + ',');
131
+ }
132
+ buf.push(`]}`);
133
+ return [buf.toString()];
134
+ }
135
+ switch (ty.kind) {
136
+ case 'int':
137
+ case 'intN':
138
+ case 'uintN':
139
+ case 'varintN':
140
+ case 'varuintN':
141
+ case 'coins': return [`{ type: 'int', value: ${tsExpr} }`];
142
+ case 'bool': return [`{ type: 'int', value: (${tsExpr} ? -1n : 0n) }`];
143
+ case 'cell': return [`{ type: 'cell', cell: ${tsExpr} }`];
144
+ case 'builder': return [`{ type: 'builder', cell: ${(0, emit_pack_unpack_1.emitMakeCellFromExpr)(ctx, tsExpr, ty)} }`];
145
+ case 'slice': return [`{ type: 'slice', cell: ${codegen_ctx_1.RUNTIME.beginCell}().storeSlice(${tsExpr}).endCell() }`];
146
+ case 'string': return [`{ type: 'cell', cell: ${codegen_ctx_1.RUNTIME.beginCell}().storeStringTail(${tsExpr}).endCell() }`];
147
+ case 'remaining': return [`{ type: 'slice', cell: ${(0, emit_pack_unpack_1.emitMakeCellFromExpr)(ctx, tsExpr, ty)} }`];
148
+ case 'address': return [`{ type: 'slice', cell: ${(0, emit_pack_unpack_1.emitMakeCellFromExpr)(ctx, tsExpr, ty)} }`];
149
+ case 'addressOpt': return emitStackWriteItems(ctx, tsExpr, { kind: 'nullable', inner: { kind: 'address' } });
150
+ case 'addressExt': return [`{ type: 'slice', cell: ${(0, emit_pack_unpack_1.emitMakeCellFromExpr)(ctx, tsExpr, ty)} }`];
151
+ case 'addressAny': return [`{ type: 'slice', cell: ${(0, emit_pack_unpack_1.emitMakeCellFromExpr)(ctx, tsExpr, ty)} }`];
152
+ case 'bitsN': return [`{ type: 'slice', cell: ${(0, emit_pack_unpack_1.emitMakeCellFromExpr)(ctx, tsExpr, ty)} }`];
153
+ case 'nullLiteral': return [`{ type: 'null' }`];
154
+ case 'callable': throw new unsupported_errors_1.NotSupportedTypeOnStack(ty, tsExpr);
155
+ case 'void': return [];
156
+ case 'unknown': return [tsExpr];
157
+ case 'nullable': {
158
+ if (ty.stack_type_id) {
159
+ let buf = new formatting_1.OutBuf();
160
+ buf.push(`...(`);
161
+ buf.push(`${tsExpr} === null ? [`);
162
+ for (let i = 0; i < ty.stack_width - 1; ++i) {
163
+ buf.push(`{ type: 'null' },`);
164
+ }
165
+ buf.push(`{ type: 'int', value: 0n },`);
166
+ buf.push(`] : [`);
167
+ emitStackWriteItems(ctx, tsExpr, ty.inner).forEach(w => buf.push(w + ','));
168
+ buf.push(`{ type: 'int', value: ${ty.stack_type_id}n },`);
169
+ buf.push(`]`);
170
+ buf.push(`) as c.TupleItem[]`);
171
+ return [buf.toString()];
172
+ }
173
+ return [`${tsExpr} === null ? { type: 'null' } : ${emitStackWriteItems(ctx, tsExpr, ty.inner)[0]}`];
174
+ }
175
+ case 'cellOf': return [`{ type: 'cell', cell: ${(0, emit_pack_unpack_1.emitMakeCellFromExpr)(ctx, `${tsExpr}.ref`, ty.inner)} }`];
176
+ case 'arrayOf': return [`{ type: 'tuple', items: ${tsExpr}.map(${formatting_1.OutBuf.onNewLine(`(ith) => (${emitStackWriteItems(ctx, 'ith', ty.inner, true)})`)})}`];
177
+ case 'tensor': return ty.items.flatMap((item, idx) => emitStackWriteItems(ctx, `${tsExpr}[${idx}]`, item));
178
+ case 'shapedTuple': {
179
+ let buf = new formatting_1.OutBuf();
180
+ buf.push(`{ type: 'tuple', items: [`);
181
+ for (let i = 0; i < ty.items.length; ++i) {
182
+ buf.push(emitStackWriteItems(ctx, `${tsExpr}[${i}]`, ty.items[i], true)[0] + ',');
183
+ }
184
+ buf.push(']}');
185
+ return [buf.toString()];
186
+ }
187
+ case 'lispListOf': {
188
+ let buf = new formatting_1.OutBuf();
189
+ buf.push(`${tsExpr}.reduceRight((tail, head) => ({ type: 'tuple', items: [`);
190
+ buf.push(emitStackWriteItems(ctx, `head`, ty.inner, true)[0] + ',');
191
+ buf.push('tail');
192
+ buf.push(`]}), { type: 'null' } as c.TupleItem)`);
193
+ return [buf.toString()];
194
+ }
195
+ case 'mapKV': return [`${tsExpr}.size === 0 ? { type: 'null' } : { type: 'cell', cell: ${codegen_ctx_1.RUNTIME.beginCell}().storeDictDirect<${(0, emit_ts_types_1.emitDictKVTypeArgs)(ctx, ty.k, ty.v)}>(${tsExpr}, ${(0, emit_pack_unpack_1.emitDictKVSerializers)(ctx, tsExpr, ty.k, ty.v)}).endCell() }`];
196
+ case 'EnumRef': return [`{ type: 'int', value: ${tsExpr} }`];
197
+ case 'StructRef': {
198
+ const structRef = ctx.symbols.getStruct(ty.struct_name);
199
+ return structRef.fields.flatMap(f => {
200
+ const fTy = ty.type_args ? (0, types_kernel_1.instantiateGenerics)(f.ty, structRef.type_params, ty.type_args) : f.ty;
201
+ return emitStackWriteItems(ctx, `${tsExpr}.${f.name}`, fTy);
202
+ });
203
+ }
204
+ case 'AliasRef': {
205
+ const aliasRef = ctx.symbols.getAlias(ty.alias_name);
206
+ const targetTy = ty.type_args ? (0, types_kernel_1.instantiateGenerics)(aliasRef.target_ty, aliasRef.type_params, ty.type_args) : aliasRef.target_ty;
207
+ return emitStackWriteItems(ctx, tsExpr, targetTy);
208
+ }
209
+ case 'genericT': throw new Error(`unexpected genericT=${ty.name_t} in '${tsExpr}'`);
210
+ case 'union': {
211
+ const variants = (0, types_kernel_1.createLabelsForUnion)(ctx.symbols, ty.variants);
212
+ variants.sort((a, b) => a.stack_type_id - b.stack_type_id); // move `null` variant (if exists) to the top
213
+ let buf = new formatting_1.OutBuf();
214
+ buf.push(`...(`);
215
+ for (let v of variants) {
216
+ if (v.labelStr === '')
217
+ buf.push(`${tsExpr} === null ? [`);
218
+ else
219
+ buf.push(`${tsExpr}.$ === '${v.labelStr}' ? [`);
220
+ for (let i = 0; i < ty.stack_width - 1 - v.stack_width; ++i) {
221
+ buf.push(`{ type: 'null' },`);
222
+ }
223
+ emitStackWriteItems(ctx, v.hasValueField ? tsExpr + '.value' : tsExpr, v.variant_ty).forEach(w => buf.push(w + ','));
224
+ buf.push(`{ type: 'int', value: ${v.stack_type_id}n },`);
225
+ buf.push(`] :`);
226
+ }
227
+ buf.push(`(() => { throw new Error('invalid $ field in a union') })()`);
228
+ buf.push(`) as c.TupleItem[]`);
229
+ return [buf.toString()];
230
+ }
231
+ }
232
+ }
@@ -0,0 +1,6 @@
1
+ import type { Ty } from './abi-types';
2
+ import { CodegenCtx } from './codegen-ctx';
3
+ import { UnionVariantLabeled } from './types-kernel';
4
+ export declare function emitUnionLabelAndValue(label: UnionVariantLabeled, contents: string): string;
5
+ export declare function emitTsType(ctx: CodegenCtx, ty: Ty): string;
6
+ export declare function emitDictKVTypeArgs(ctx: CodegenCtx, tyK: Ty, tyV: Ty): string;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.emitUnionLabelAndValue = emitUnionLabelAndValue;
4
+ exports.emitTsType = emitTsType;
5
+ exports.emitDictKVTypeArgs = emitDictKVTypeArgs;
6
+ const formatting_1 = require("./formatting");
7
+ const types_kernel_1 = require("./types-kernel");
8
+ // Given a union `T1 | T2` after detecting whether each `T_i` should have `$ + value`,
9
+ // stringify it
10
+ function emitUnionLabelAndValue(label, contents) {
11
+ return label.hasValueField ? `{ $: '${label.labelStr}', value: ${contents} }` : contents;
12
+ }
13
+ // Convert any Tolk type (ABI representation) to a corresponding TypeScript type.
14
+ // Tolk `int32` -> TS `bigint`, but for readability, `type int32 = bigint` is created.
15
+ // `c.` is import @ton/core.
16
+ function emitTsType(ctx, ty) {
17
+ if (ty.kind === 'intN')
18
+ ctx.intNOccurred.add(`int${ty.n}`);
19
+ if (ty.kind === 'uintN')
20
+ ctx.uintNOccurred.add(`uint${ty.n}`);
21
+ if (ty.kind === 'varintN')
22
+ ctx.varIntNOccurred.add(`varint${ty.n}`);
23
+ if (ty.kind === 'varuintN')
24
+ ctx.varIntNOccurred.add(`varuint${ty.n}`);
25
+ if (ty.kind === 'bitsN')
26
+ ctx.bitsNOccurred.add(`bits${ty.n}`);
27
+ if (ty.kind === 'remaining')
28
+ ctx.has_RemainingBitsAndRefs = true;
29
+ if (ty.kind === 'addressAny')
30
+ ctx.has_addressAny = true;
31
+ if (ty.kind === 'arrayOf')
32
+ ctx.has_arrayOf = true;
33
+ if (ty.kind === 'lispListOf')
34
+ ctx.has_lispListOf = true;
35
+ switch (ty.kind) {
36
+ case 'int': return `bigint`;
37
+ case 'intN': return `int${ty.n}`;
38
+ case 'uintN': return `uint${ty.n}`;
39
+ case 'varintN': return `varint${ty.n}`;
40
+ case 'varuintN': return `varuint${ty.n}`;
41
+ case 'coins': return `coins`;
42
+ case 'bool': return `boolean`;
43
+ case 'cell': return `c.Cell`;
44
+ case 'builder': return `c.Builder`;
45
+ case 'slice': return `c.Slice`;
46
+ case 'string': return 'string';
47
+ case 'remaining': return `RemainingBitsAndRefs`;
48
+ case 'address': return `c.Address`;
49
+ case 'addressOpt': return `c.Address | null`;
50
+ case 'addressExt': return `c.ExternalAddress`;
51
+ case 'addressAny': return `any_address`;
52
+ case 'bitsN': return `bits${ty.n}`;
53
+ case 'nullLiteral': return `null`;
54
+ case 'callable': return `any`;
55
+ case 'void': return `void`;
56
+ case 'unknown': return `c.TupleItem`;
57
+ case 'nullable': return `${emitTsType(ctx, ty.inner)} | null`;
58
+ case 'cellOf': return `CellRef<${emitTsType(ctx, ty.inner)}>`;
59
+ case 'arrayOf': return `array<${emitTsType(ctx, ty.inner)}>`;
60
+ case 'lispListOf': return `lisp_list<${emitTsType(ctx, ty.inner)}>`;
61
+ case 'tensor': return `[${ty.items.map(item => emitTsType(ctx, item)).join(', ')}]`;
62
+ case 'shapedTuple': return `[${ty.items.map(item => emitTsType(ctx, item)).join(', ')}]`;
63
+ case 'mapKV': return `c.Dictionary<${emitDictKVTypeArgs(ctx, ty.k, ty.v)}>`;
64
+ case 'EnumRef': return ty.enum_name;
65
+ case 'StructRef': return (0, formatting_1.safeJsIdent)(ty.struct_name) + (ty.type_args ? `<${ty.type_args.map(ta => emitTsType(ctx, ta)).join(', ')}>` : '');
66
+ case 'AliasRef': return (0, formatting_1.safeJsIdent)(ty.alias_name) + (ty.type_args ? `<${ty.type_args.map(ta => emitTsType(ctx, ta)).join(', ')}>` : '');
67
+ case 'genericT': return ty.name_t;
68
+ case 'union': return (0, types_kernel_1.createLabelsForUnion)(ctx.symbols, ty.variants).map(v => emitUnionLabelAndValue(v, emitTsType(ctx, v.variant_ty))).join(' | ');
69
+ }
70
+ }
71
+ // Emit c.Dictionary<K, V> (K and V — inside brackets, two types separated by comma).
72
+ function emitDictKVTypeArgs(ctx, tyK, tyV) {
73
+ return emitTsType(ctx, tyK) + ', ' + emitTsType(ctx, tyV);
74
+ }
@@ -0,0 +1,15 @@
1
+ export declare class OutBuf {
2
+ static TAB: string;
3
+ static onNewLine(s: string): string;
4
+ private static indentNested;
5
+ private lines;
6
+ private indentLevel;
7
+ indent(): void;
8
+ outdent(): void;
9
+ emptyLine(): void;
10
+ push(line: string): this;
11
+ toString(): string;
12
+ }
13
+ export declare function safeJsIdent(tolkIdentifier: string): string;
14
+ export declare function safeFieldDecl(fieldName: string): string;
15
+ export declare function safeFieldRead(fieldName: string): string;