@quenk/wml 2.13.11 → 2.14.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.
- package/lib/cli.d.ts +8 -8
- package/lib/cli.js +1 -3
- package/lib/cli.js.map +1 -1
- package/lib/cli.ts +48 -60
- package/lib/compile/codegen.d.ts +4 -9
- package/lib/compile/codegen.js +161 -367
- package/lib/compile/codegen.js.map +1 -1
- package/lib/compile/codegen.ts +643 -952
- package/lib/compile/index.d.ts +2 -2
- package/lib/compile/index.js +4 -4
- package/lib/compile/index.js.map +1 -1
- package/lib/compile/index.ts +14 -17
- package/lib/compile/transform.d.ts +1 -1
- package/lib/compile/transform.js +9 -11
- package/lib/compile/transform.js.map +1 -1
- package/lib/compile/transform.ts +136 -143
- package/lib/{dom.d.ts → dom/index.d.ts} +8 -2
- package/lib/{dom.js → dom/index.js} +84 -70
- package/lib/dom/index.js.map +1 -0
- package/lib/dom/index.ts +425 -0
- package/lib/dom/monitor.d.ts +33 -0
- package/lib/dom/monitor.js +60 -0
- package/lib/dom/monitor.js.map +1 -0
- package/lib/dom/monitor.ts +75 -0
- package/lib/index.d.ts +10 -95
- package/lib/index.js +10 -10
- package/lib/index.js.map +1 -1
- package/lib/index.ts +57 -182
- package/lib/main.js +17 -17
- package/lib/main.js.map +1 -1
- package/lib/main.ts +38 -44
- package/lib/parse/ast.d.ts +2 -2
- package/lib/parse/ast.js +52 -53
- package/lib/parse/ast.js.map +1 -1
- package/lib/parse/ast.ts +396 -483
- package/lib/parse/generated.d.ts +3 -5
- package/lib/parse/generated.js +9504 -9264
- package/lib/parse/index.d.ts +2 -3
- package/lib/parse/index.js.map +1 -1
- package/lib/parse/index.ts +7 -9
- package/lib/parse/test.js +194 -192
- package/lib/parse/test.js.map +1 -1
- package/lib/parse/test.ts +294 -404
- package/lib/parse/wml.y +4 -0
- package/lib/tsconfig.json +19 -20
- package/lib/util.d.ts +10 -0
- package/lib/util.js +21 -0
- package/lib/util.js.map +1 -0
- package/lib/util.ts +39 -0
- package/lib/view/frame.d.ts +127 -0
- package/lib/view/frame.js +214 -0
- package/lib/view/frame.js.map +1 -0
- package/lib/view/frame.ts +295 -0
- package/lib/view/index.d.ts +58 -0
- package/lib/view/index.js +48 -0
- package/lib/view/index.js.map +1 -0
- package/lib/view/index.ts +98 -0
- package/package.json +3 -3
- package/lib/dom.js.map +0 -1
- package/lib/dom.ts +0 -479
package/lib/compile/codegen.ts
CHANGED
|
@@ -4,63 +4,33 @@
|
|
|
4
4
|
|
|
5
5
|
/** imports */
|
|
6
6
|
|
|
7
|
-
import * as ast from
|
|
7
|
+
import * as ast from "../parse/ast";
|
|
8
8
|
|
|
9
|
-
import { set } from
|
|
9
|
+
import { set } from "@quenk/noni/lib/data/record/path";
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} from
|
|
17
|
-
import { contains, empty, find, partition } from
|
|
11
|
+
Record,
|
|
12
|
+
merge,
|
|
13
|
+
mapTo,
|
|
14
|
+
reduce,
|
|
15
|
+
isRecord,
|
|
16
|
+
} from "@quenk/noni/lib/data/record";
|
|
17
|
+
import { contains, empty, find, partition } from "@quenk/noni/lib/data/array";
|
|
18
18
|
|
|
19
|
-
import { transformTree } from
|
|
19
|
+
import { transformTree } from "./transform";
|
|
20
20
|
|
|
21
|
-
export const CONTEXT =
|
|
22
|
-
export const VIEW =
|
|
23
|
-
export const WML =
|
|
24
|
-
export const DOCUMENT =
|
|
25
|
-
export const
|
|
21
|
+
export const CONTEXT = "__context";
|
|
22
|
+
export const VIEW = "__view";
|
|
23
|
+
export const WML = "__wml";
|
|
24
|
+
export const DOCUMENT = "__document";
|
|
25
|
+
export const UTILS = "__utils";
|
|
26
|
+
export const THIS = "__this";
|
|
27
|
+
export const VIEW_FRAME = "__viewFrame";
|
|
26
28
|
|
|
27
|
-
const
|
|
29
|
+
const VIEW_CLASS = "BaseView";
|
|
30
|
+
const FRAME_TYPE = "Frame";
|
|
28
31
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
const FROM_ARRAY = '__fromArray';
|
|
32
|
-
|
|
33
|
-
const NODE_PARAMS = `tag:string, attrs:${WML}.Attrs, ` +
|
|
34
|
-
`children: ${WML}.Content[]`;
|
|
35
|
-
|
|
36
|
-
const WIDGET_PARAMS =
|
|
37
|
-
`w: ${WML}.Widget, attrs:${WML}.Attrs`;
|
|
38
|
-
|
|
39
|
-
const REGISTER_VIEW_PARAMS = `v:${WML}.View`;
|
|
40
|
-
|
|
41
|
-
const REGISTER_PARAMS = `e:${WML}.WMLElement, ` +
|
|
42
|
-
`attrs:${WML}.Attributes<any>`;
|
|
43
|
-
|
|
44
|
-
const THROW_INVALIDATE_ERR = ` throw new Error('invalidate(): cannot ` +
|
|
45
|
-
`invalidate this view, it has no parent node!');`;
|
|
46
|
-
|
|
47
|
-
const IGNORE_UNUSED = '//@ts-ignore:6192';
|
|
48
|
-
|
|
49
|
-
const RECORD = '__Record<A>';
|
|
50
|
-
|
|
51
|
-
const IF = '__if';
|
|
52
|
-
|
|
53
|
-
const IFARG = `__IfArg`;
|
|
54
|
-
|
|
55
|
-
const FOR_OF = '__forOf';
|
|
56
|
-
|
|
57
|
-
const FOR_IN = '__forIn';
|
|
58
|
-
|
|
59
|
-
const FOR_ALT_TYPE = '__ForAlt';
|
|
60
|
-
|
|
61
|
-
const FOR_IN_BODY = '__ForInBody<A>';
|
|
62
|
-
|
|
63
|
-
const FOR_OF_BODY = '__ForOfBody<A>';
|
|
32
|
+
const FOR_OF = `${UTILS}.forOf`;
|
|
33
|
+
const FOR_IN = `${UTILS}.forIn`;
|
|
64
34
|
|
|
65
35
|
/**
|
|
66
36
|
* TypeScript code.
|
|
@@ -75,59 +45,55 @@ export type TypeOrMap = TypeScript | ExpandedTypeMap;
|
|
|
75
45
|
/**
|
|
76
46
|
* TypeMap contains a recursive map of dotted paths to Type nodes.
|
|
77
47
|
*/
|
|
78
|
-
export interface TypeMap extends Record<ast.Type> {
|
|
48
|
+
export interface TypeMap extends Record<ast.Type> {}
|
|
79
49
|
|
|
80
50
|
/**
|
|
81
51
|
* ExpandedTypeMap is an expanded version of TypeMap.
|
|
82
52
|
*
|
|
83
|
-
* Each dotted path is expanded recursively into records
|
|
53
|
+
* Each dotted path is expanded recursively into records
|
|
84
54
|
* so that no path contain dots.
|
|
85
55
|
*/
|
|
86
|
-
export interface ExpandedTypeMap extends Record<TypeOrMap> {
|
|
56
|
+
export interface ExpandedTypeMap extends Record<TypeOrMap> {}
|
|
87
57
|
|
|
88
58
|
const prims = [
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
59
|
+
"String",
|
|
60
|
+
"Boolean",
|
|
61
|
+
"Number",
|
|
62
|
+
"Object",
|
|
63
|
+
"Undefined",
|
|
64
|
+
"Null",
|
|
65
|
+
"Void",
|
|
66
|
+
"Never",
|
|
67
|
+
"Any",
|
|
98
68
|
];
|
|
99
69
|
|
|
100
|
-
const casters = [
|
|
70
|
+
const casters = ["String", "Boolean", "Number", "Object"];
|
|
101
71
|
|
|
102
72
|
const operators: { [key: string]: string } = {
|
|
73
|
+
"==": "===",
|
|
103
74
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
'!=': '!=='
|
|
107
|
-
|
|
108
|
-
}
|
|
75
|
+
"!=": "!==",
|
|
76
|
+
};
|
|
109
77
|
|
|
110
78
|
/**
|
|
111
79
|
* CodeGeneratorOptions
|
|
112
80
|
*/
|
|
113
81
|
export interface CodeGeneratorOptions {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
EOL: string
|
|
130
|
-
|
|
82
|
+
/**
|
|
83
|
+
* module path that wml types will be imported from in the output.
|
|
84
|
+
*/
|
|
85
|
+
module: string;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* dom is the module path that the wml DOM api will be imported from in the
|
|
89
|
+
* output.
|
|
90
|
+
*/
|
|
91
|
+
dom: string;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* EOL character to use when terminating lines.
|
|
95
|
+
*/
|
|
96
|
+
EOL: string;
|
|
131
97
|
}
|
|
132
98
|
|
|
133
99
|
/**
|
|
@@ -138,294 +104,182 @@ export interface CodeGeneratorOptions {
|
|
|
138
104
|
* provide a typescript module.
|
|
139
105
|
*/
|
|
140
106
|
export class CodeGenerator {
|
|
107
|
+
constructor(public options: CodeGeneratorOptions) {}
|
|
141
108
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
return new CodeGenerator(opts);
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* generate a Typescript module from an WML AST.
|
|
155
|
-
*/
|
|
156
|
-
generate(tree: ast.Module): TypeScript {
|
|
157
|
-
|
|
158
|
-
tree = transformTree(tree);
|
|
109
|
+
/**
|
|
110
|
+
* create a new CodeGenerator instance.
|
|
111
|
+
*/
|
|
112
|
+
static create(opts: CodeGeneratorOptions): CodeGenerator {
|
|
113
|
+
return new CodeGenerator(opts);
|
|
114
|
+
}
|
|
159
115
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
importStatements2TS(this, tree.imports),
|
|
166
|
-
eol(this),
|
|
167
|
-
typeDefinitions(this),
|
|
168
|
-
eol(this),
|
|
169
|
-
`// @ts-ignore 6192`,
|
|
170
|
-
`const text = ${DOCUMENT}.text;`,
|
|
171
|
-
`// @ts-ignore 6192`,
|
|
172
|
-
`const unsafe = ${DOCUMENT}.unsafe`,
|
|
173
|
-
`// @ts-ignore 6192`,
|
|
174
|
-
`const isSet = (value:any) => value != null`,
|
|
175
|
-
exports2TS(this, tree.exports)
|
|
176
|
-
|
|
177
|
-
].join(eol(this));
|
|
178
|
-
|
|
179
|
-
}
|
|
116
|
+
/**
|
|
117
|
+
* generate a Typescript module from an WML AST.
|
|
118
|
+
*/
|
|
119
|
+
generate(tree: ast.Module): TypeScript {
|
|
120
|
+
tree = transformTree(tree);
|
|
180
121
|
|
|
122
|
+
return [
|
|
123
|
+
`// @ts-ignore 6192`,
|
|
124
|
+
`import * as ${WML} from '${this.options.module}';`,
|
|
125
|
+
`// @ts-ignore 6192`,
|
|
126
|
+
`import * as ${DOCUMENT} from '${this.options.module}/lib/dom';`,
|
|
127
|
+
`// @ts-ignore 6192`,
|
|
128
|
+
`import * as ${UTILS} from '${this.options.module}/lib/util';`,
|
|
129
|
+
importStatements2TS(this, tree.imports),
|
|
130
|
+
eol(this),
|
|
131
|
+
`// @ts-ignore 6192`,
|
|
132
|
+
`const text = ${DOCUMENT}.text;`,
|
|
133
|
+
`// @ts-ignore 6192`,
|
|
134
|
+
`const unsafe = ${DOCUMENT}.unsafe`,
|
|
135
|
+
`// @ts-ignore 6192`,
|
|
136
|
+
`const isSet = ${UTILS}.isSet`,
|
|
137
|
+
exports2TS(this, tree.exports),
|
|
138
|
+
].join(eol(this));
|
|
139
|
+
}
|
|
181
140
|
}
|
|
182
141
|
|
|
183
142
|
const eol = (ctx: CodeGenerator) => `${ctx.options.EOL}`;
|
|
184
143
|
|
|
185
|
-
const imports = (ctx: CodeGenerator) => [
|
|
186
|
-
`//@ts-ignore: 6192`,
|
|
187
|
-
`import {`,
|
|
188
|
-
`Maybe as ${MAYBE},`,
|
|
189
|
-
`fromNullable as ${FROM_NULLABLE},`,
|
|
190
|
-
`fromArray as ${FROM_ARRAY}`,
|
|
191
|
-
`}`,
|
|
192
|
-
`from '@quenk/noni/lib/data/maybe';`
|
|
193
|
-
].join(eol(ctx));
|
|
194
|
-
|
|
195
|
-
const typeDefinitions = (ctx: CodeGenerator) => [
|
|
196
|
-
`${IGNORE_UNUSED}`,
|
|
197
|
-
`type ${IFARG} = ()=>${WML}.Content[]`,
|
|
198
|
-
``,
|
|
199
|
-
`${IGNORE_UNUSED}`,
|
|
200
|
-
`type ${FOR_ALT_TYPE} = ()=> ${WML}.Content[]`,
|
|
201
|
-
``,
|
|
202
|
-
`${IGNORE_UNUSED}`,
|
|
203
|
-
`type ${FOR_IN_BODY} =(val:A, idx:number, all:A[])=>` +
|
|
204
|
-
`${WML}.Content[]`,
|
|
205
|
-
``,
|
|
206
|
-
`${IGNORE_UNUSED}`,
|
|
207
|
-
`type ${FOR_OF_BODY} = (val:A, key:string, all:object) =>` +
|
|
208
|
-
`${WML}.Content[]`,
|
|
209
|
-
``,
|
|
210
|
-
`${IGNORE_UNUSED}`,
|
|
211
|
-
`interface ${RECORD} {`,
|
|
212
|
-
``,
|
|
213
|
-
` [key:string]: A`,
|
|
214
|
-
``,
|
|
215
|
-
`}`,
|
|
216
|
-
``,
|
|
217
|
-
`${IGNORE_UNUSED}`,
|
|
218
|
-
`const ${IF} = (__expr:boolean, __conseq:${IFARG},__alt?:${IFARG}) ` +
|
|
219
|
-
`: Content[]=>`,
|
|
220
|
-
`(__expr) ? __conseq() : __alt ? __alt() : [];`,
|
|
221
|
-
``,
|
|
222
|
-
`${IGNORE_UNUSED}`,
|
|
223
|
-
`const ${FOR_IN} = <A>(list:A[], f:${FOR_IN_BODY}, alt:` +
|
|
224
|
-
`${FOR_ALT_TYPE}) : ${WML}.Content[] => {`,
|
|
225
|
-
``,
|
|
226
|
-
` let ret:${WML}.Content[] = [];`,
|
|
227
|
-
``,
|
|
228
|
-
` for(let i=0; i<list.length; i++)`,
|
|
229
|
-
` ret = ret.concat(f(list[i], i, list));`,
|
|
230
|
-
``,
|
|
231
|
-
` return ret.length === 0 ? alt() : ret;`,
|
|
232
|
-
``,
|
|
233
|
-
`}`,
|
|
234
|
-
`${IGNORE_UNUSED}`,
|
|
235
|
-
`const ${FOR_OF} = <A>(o:${RECORD}, f:${FOR_OF_BODY},` +
|
|
236
|
-
`alt:${FOR_ALT_TYPE}) : ${WML}.Content[] => {`,
|
|
237
|
-
``,
|
|
238
|
-
` let ret:${WML}.Content[] = [];`,
|
|
239
|
-
``,
|
|
240
|
-
` for(let key in o)`,
|
|
241
|
-
` if(o.hasOwnProperty(key)) `,
|
|
242
|
-
` ret = ret.concat(f((o)[key], key, o));`,
|
|
243
|
-
``,
|
|
244
|
-
` return ret.length === 0 ? alt(): ret;`,
|
|
245
|
-
``,
|
|
246
|
-
`}`
|
|
247
|
-
|
|
248
|
-
].join(eol(ctx));
|
|
249
|
-
|
|
250
144
|
/**
|
|
251
145
|
* importStatements2TS converts a list of ImportStatements into typescript.
|
|
252
146
|
*/
|
|
253
|
-
export const importStatements2TS =
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
147
|
+
export const importStatements2TS = (
|
|
148
|
+
ctx: CodeGenerator,
|
|
149
|
+
list: ast.ImportStatement[],
|
|
150
|
+
): TypeScript =>
|
|
151
|
+
list
|
|
152
|
+
.map(importStatement2TS)
|
|
153
|
+
.filter((stmt, idx, list) => list.indexOf(stmt) == idx)
|
|
154
|
+
.join(`;${eol(ctx)}`);
|
|
259
155
|
|
|
260
156
|
/**
|
|
261
|
-
* importStatement2TS
|
|
157
|
+
* importStatement2TS
|
|
262
158
|
*/
|
|
263
159
|
export const importStatement2TS = (n: ast.ImportStatement): TypeScript =>
|
|
264
|
-
|
|
160
|
+
`import ${importMember2TS(n.member)} from '${n.module.value.trim()}'; `;
|
|
265
161
|
|
|
266
162
|
/**
|
|
267
163
|
* importMember2TS
|
|
268
164
|
*/
|
|
269
165
|
export const importMember2TS = (n: ast.ImportMember): string => {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
else if (n instanceof ast.CompositeMember)
|
|
276
|
-
return compositeMember2TS(n);
|
|
277
|
-
else
|
|
278
|
-
return '';
|
|
279
|
-
|
|
280
|
-
}
|
|
166
|
+
if (n instanceof ast.AggregateMember) return aggregateMember2TS(n);
|
|
167
|
+
else if (n instanceof ast.AliasedMember) return aliasedMember2TS(n);
|
|
168
|
+
else if (n instanceof ast.CompositeMember) return compositeMember2TS(n);
|
|
169
|
+
else return "";
|
|
170
|
+
};
|
|
281
171
|
|
|
282
172
|
/**
|
|
283
173
|
* aggregateMember2TS
|
|
284
174
|
*/
|
|
285
175
|
export const aggregateMember2TS = (n: ast.AggregateMember): string =>
|
|
286
|
-
|
|
176
|
+
`* as ${identifierOrConstructor2TS(n.id)} `;
|
|
287
177
|
|
|
288
178
|
/**
|
|
289
179
|
* aliasedMember2TS
|
|
290
180
|
*/
|
|
291
181
|
export const aliasedMember2TS = (n: ast.AliasedMember): string =>
|
|
292
|
-
|
|
293
|
-
|
|
182
|
+
`${identifierOrConstructor2TS(n.member)} ` +
|
|
183
|
+
`as ${identifierOrConstructor2TS(n.alias)} `;
|
|
294
184
|
|
|
295
185
|
/**
|
|
296
|
-
* compositeMember2TS
|
|
186
|
+
* compositeMember2TS
|
|
297
187
|
*/
|
|
298
188
|
export const compositeMember2TS = (n: ast.CompositeMember): string =>
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
189
|
+
"{" +
|
|
190
|
+
n.members
|
|
191
|
+
.map((m) =>
|
|
192
|
+
m instanceof ast.AliasedMember
|
|
193
|
+
? aliasedMember2TS(m)
|
|
194
|
+
: identifierOrConstructor2TS(m),
|
|
195
|
+
)
|
|
196
|
+
.join(",") +
|
|
197
|
+
"}";
|
|
302
198
|
|
|
303
199
|
/**
|
|
304
200
|
* exports2TS converts a list of exports to typescript.
|
|
305
201
|
*/
|
|
306
202
|
export const exports2TS = (ctx: CodeGenerator, list: ast.Export[]) =>
|
|
307
|
-
|
|
203
|
+
list.map((e) => export2TS(ctx, e)).join(";" + eol(ctx));
|
|
308
204
|
|
|
309
205
|
/**
|
|
310
|
-
* export2TS
|
|
206
|
+
* export2TS
|
|
311
207
|
*/
|
|
312
208
|
export const export2TS = (ctx: CodeGenerator, n: ast.Export) => {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
return funStatement2TS(ctx, n);
|
|
322
|
-
else if (n instanceof ast.ViewStatement)
|
|
323
|
-
return viewStatement2TS(ctx, n);
|
|
324
|
-
else if ((n instanceof ast.Widget) || (n instanceof ast.Node))
|
|
325
|
-
return tag2TS(ctx, n);
|
|
326
|
-
else
|
|
327
|
-
return '';
|
|
328
|
-
|
|
329
|
-
}
|
|
209
|
+
if (n instanceof ast.AliasStatement) return aliasStatement2TS(n);
|
|
210
|
+
else if (n instanceof ast.ContextStatement) return contextStatement2TS(n);
|
|
211
|
+
else if (n instanceof ast.LetStatement) return letStatement2TS(ctx, n);
|
|
212
|
+
else if (n instanceof ast.ViewStatement) return viewStatement2TS(ctx, n);
|
|
213
|
+
else if (n instanceof ast.Widget || n instanceof ast.Node)
|
|
214
|
+
return tag2TS(ctx, n);
|
|
215
|
+
else return "";
|
|
216
|
+
};
|
|
330
217
|
|
|
331
218
|
/**
|
|
332
219
|
* aliasStatement2TS
|
|
333
220
|
*/
|
|
334
221
|
export const aliasStatement2TS = (n: ast.AliasStatement) => {
|
|
222
|
+
let typeArgs =
|
|
223
|
+
n.typeParameters.length > 0 ? typeParameters2TS(n.typeParameters) : "";
|
|
335
224
|
|
|
336
|
-
|
|
337
|
-
typeParameters2TS(n.typeParameters) : '';
|
|
338
|
-
|
|
339
|
-
let preamble = `export type ${n.id.value}${typeArgs}`;
|
|
340
|
-
|
|
341
|
-
let members = n.members.map(m => type2TS(m)).join('|');
|
|
225
|
+
let preamble = `export type ${n.id.value}${typeArgs}`;
|
|
342
226
|
|
|
343
|
-
|
|
227
|
+
let members = n.members.map((m) => type2TS(m)).join("|");
|
|
344
228
|
|
|
345
|
-
}
|
|
229
|
+
return `${preamble} = ${members};`;
|
|
230
|
+
};
|
|
346
231
|
|
|
347
232
|
/**
|
|
348
233
|
* contextStatement2TS
|
|
349
234
|
*/
|
|
350
235
|
export const contextStatement2TS = (n: ast.ContextStatement) => {
|
|
236
|
+
let preamble = `export interface ${n.id.value}`;
|
|
351
237
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
let typeArgs = (n.typeParameters.length > 0) ?
|
|
355
|
-
typeParameters2TS(n.typeParameters) : '';
|
|
238
|
+
let typeArgs =
|
|
239
|
+
n.typeParameters.length > 0 ? typeParameters2TS(n.typeParameters) : "";
|
|
356
240
|
|
|
357
|
-
|
|
358
|
-
|
|
241
|
+
let [parents, members] = partition(
|
|
242
|
+
n.members,
|
|
243
|
+
(member) => member instanceof ast.ConstructorType,
|
|
244
|
+
);
|
|
359
245
|
|
|
360
|
-
|
|
361
|
-
|
|
246
|
+
let parentList = (<ast.ConstructorType[]>parents)
|
|
247
|
+
.map(constructorType2TS)
|
|
248
|
+
.join(",");
|
|
362
249
|
|
|
363
|
-
|
|
250
|
+
parentList = parentList !== "" ? ` extends ${parentList}` : "";
|
|
364
251
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
252
|
+
return [
|
|
253
|
+
preamble,
|
|
254
|
+
typeArgs,
|
|
255
|
+
parentList,
|
|
256
|
+
"{",
|
|
257
|
+
memberDeclarations2TS(<ast.MemberDeclaration[]>members),
|
|
258
|
+
"}",
|
|
259
|
+
].join("");
|
|
260
|
+
};
|
|
375
261
|
|
|
376
262
|
/**
|
|
377
263
|
* letStatement2TS
|
|
378
264
|
*/
|
|
379
|
-
export const letStatement2TS =
|
|
380
|
-
|
|
381
|
-
_setStatement2TS(ctx, n, 'export const');
|
|
382
|
-
|
|
383
|
-
const _setStatement2TS =
|
|
384
|
-
(ctx: CodeGenerator, n: ast.LetStatement, preamble: string) => {
|
|
385
|
-
|
|
386
|
-
let id = identifier2TS(n.id);
|
|
265
|
+
export const letStatement2TS = (ctx: CodeGenerator, n: ast.LetStatement) =>
|
|
266
|
+
_setStatement2TS(ctx, n, "export const");
|
|
387
267
|
|
|
388
|
-
|
|
268
|
+
const _setStatement2TS = (
|
|
269
|
+
ctx: CodeGenerator,
|
|
270
|
+
n: ast.LetStatement,
|
|
271
|
+
preamble: string,
|
|
272
|
+
) => {
|
|
273
|
+
let id = identifier2TS(n.id);
|
|
389
274
|
|
|
390
|
-
|
|
275
|
+
let cons = constructorType2TS(n.cons);
|
|
391
276
|
|
|
392
|
-
|
|
277
|
+
preamble = `${preamble} ${id}:${cons}`;
|
|
393
278
|
|
|
394
|
-
|
|
279
|
+
let value = expression2TS(ctx, n.expression);
|
|
395
280
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* funStatement2TS generates Typescript output for fun statements.
|
|
400
|
-
*
|
|
401
|
-
* This is a curried function that first accepts zero or more arguments then
|
|
402
|
-
* a single Registry, finally the content.
|
|
403
|
-
*/
|
|
404
|
-
export const funStatement2TS = (ctx: CodeGenerator, n: ast.FunStatement) => {
|
|
405
|
-
|
|
406
|
-
let id = unqualifiedIdentifier2TS(n.id);
|
|
407
|
-
|
|
408
|
-
let typeParams = typeParameters2TS(n.typeParameters);
|
|
409
|
-
|
|
410
|
-
let params = parameters2TS(n.parameters);
|
|
411
|
-
|
|
412
|
-
let factory = `(${THIS}:${WML}.Registry) : ${WML}.Content[] =>`;
|
|
413
|
-
|
|
414
|
-
let body = children2TS(ctx, n.body);
|
|
415
|
-
|
|
416
|
-
return [
|
|
417
|
-
|
|
418
|
-
`export const ${id} = `,
|
|
419
|
-
``,
|
|
420
|
-
`${typeParams}(${params})=>${factory} {`,
|
|
421
|
-
``,
|
|
422
|
-
` return ${body};`,
|
|
423
|
-
``,
|
|
424
|
-
`};`
|
|
425
|
-
|
|
426
|
-
].join(eol(ctx));
|
|
427
|
-
|
|
428
|
-
}
|
|
281
|
+
return `${preamble} = ${value}`;
|
|
282
|
+
};
|
|
429
283
|
|
|
430
284
|
/**
|
|
431
285
|
* viewStatement2TS converts a ViewStatement to its typescript form.
|
|
@@ -433,247 +287,116 @@ export const funStatement2TS = (ctx: CodeGenerator, n: ast.FunStatement) => {
|
|
|
433
287
|
* This is a class with template and various useful helpers.
|
|
434
288
|
*/
|
|
435
289
|
export const viewStatement2TS = (ctx: CodeGenerator, n: ast.ViewStatement) => {
|
|
290
|
+
let instances = n.directives
|
|
291
|
+
.map((i) => _setStatement2TS(ctx, i, "let"))
|
|
292
|
+
.join(`;${ctx.options.EOL}`);
|
|
436
293
|
|
|
437
|
-
|
|
438
|
-
_setStatement2TS(ctx, i, 'let')).join(`;${ctx.options.EOL}`);
|
|
294
|
+
let id = n.id ? constructor2TS(n.id) : "Main";
|
|
439
295
|
|
|
440
|
-
|
|
296
|
+
let typeParams = typeParameters2TS(n.typeParameters);
|
|
441
297
|
|
|
442
|
-
|
|
298
|
+
let context = n.context
|
|
299
|
+
? type2TS(
|
|
300
|
+
n.context instanceof ast.ContextFromStatement
|
|
301
|
+
? n.context.cons
|
|
302
|
+
: <ast.ConstructorType>n.context,
|
|
303
|
+
)
|
|
304
|
+
: "object";
|
|
443
305
|
|
|
444
|
-
|
|
445
|
-
n.context.cons : <ast.ConstructorType>n.context);
|
|
306
|
+
let defaultContext = n.context ? "" : "={}";
|
|
446
307
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
return [
|
|
308
|
+
let template = tag2TS(ctx, n.root);
|
|
450
309
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
``,
|
|
471
|
-
` widgets: ${WML}.Widget[] = [];`,
|
|
472
|
-
``,
|
|
473
|
-
` tree: Node = <Node>${DOCUMENT}.createElement('div');`,
|
|
474
|
-
``,
|
|
475
|
-
` template: ${WML}.Template;`,
|
|
476
|
-
``,
|
|
477
|
-
` registerView(${REGISTER_VIEW_PARAMS}) : ${WML}.View {`,
|
|
478
|
-
``,
|
|
479
|
-
` this.views.push(v);`,
|
|
480
|
-
``,
|
|
481
|
-
` return v;`,
|
|
482
|
-
``,
|
|
483
|
-
`}`,
|
|
484
|
-
` register(${REGISTER_PARAMS}) : ${WML}.WMLElement {`,
|
|
485
|
-
``,
|
|
486
|
-
` let attrsMap = (<${WML}.Attrs><any>attrs)`,
|
|
487
|
-
``,
|
|
488
|
-
` if(attrsMap.wml) {`,
|
|
489
|
-
``,
|
|
490
|
-
` let {id, group} = attrsMap.wml;`,
|
|
491
|
-
``,
|
|
492
|
-
` if(id != null) {`,
|
|
493
|
-
``,
|
|
494
|
-
` if (this.ids.hasOwnProperty(id))`,
|
|
495
|
-
` throw new Error(\`Duplicate id '\${id}' detected!\`);`,
|
|
496
|
-
``,
|
|
497
|
-
` this.ids[id] = e;`,
|
|
498
|
-
``,
|
|
499
|
-
` }`,
|
|
500
|
-
``,
|
|
501
|
-
` if(group != null) {`,
|
|
502
|
-
``,
|
|
503
|
-
` this.groups[group] = this.groups[group] || [];`,
|
|
504
|
-
` this.groups[group].push(e);`,
|
|
505
|
-
``,
|
|
506
|
-
` }`,
|
|
507
|
-
``,
|
|
508
|
-
` }`,
|
|
509
|
-
` return e;`,
|
|
510
|
-
`}`,
|
|
511
|
-
``,
|
|
512
|
-
` node(${NODE_PARAMS}): ${WML}.Content {`,
|
|
513
|
-
``,
|
|
514
|
-
` let asDOMAttrs = <${DOCUMENT}.WMLDOMAttrs><object>attrs`,
|
|
515
|
-
``,
|
|
516
|
-
` let e = ${DOCUMENT}.createElement(tag, asDOMAttrs, children,`,
|
|
517
|
-
` attrs.wml && attrs.wml.ns || '');`,
|
|
518
|
-
``,
|
|
519
|
-
` this.register(e, attrs);`,
|
|
520
|
-
``,
|
|
521
|
-
` return e;`,
|
|
522
|
-
``,
|
|
523
|
-
` }`,
|
|
524
|
-
``,
|
|
525
|
-
``,
|
|
526
|
-
` widget(${WIDGET_PARAMS}) : ${WML}.Content {`,
|
|
527
|
-
``,
|
|
528
|
-
` this.register(w, attrs);`,
|
|
529
|
-
``,
|
|
530
|
-
` this.widgets.push(w);`,
|
|
531
|
-
``,
|
|
532
|
-
` return w.render();`,
|
|
533
|
-
``,
|
|
534
|
-
` }`,
|
|
535
|
-
``,
|
|
536
|
-
` findById<E extends ${WML}.WMLElement>(id: string): ${MAYBE}<E> {`,
|
|
537
|
-
``,
|
|
538
|
-
` let mW:${MAYBE}<E> = ${FROM_NULLABLE}<E>(<E>this.ids[id])`,
|
|
539
|
-
``,
|
|
540
|
-
` return this.views.reduce((p,c)=>`,
|
|
541
|
-
` p.isJust() ? p : c.findById(id), mW);`,
|
|
542
|
-
``,
|
|
543
|
-
` }`,
|
|
544
|
-
``,
|
|
545
|
-
` findGroupById<E extends ${WML}.WMLElement>(name: string): E[] {` +
|
|
546
|
-
``,
|
|
547
|
-
` return this.groups.hasOwnProperty(name) ?`,
|
|
548
|
-
` <E[]>this.groups[name] : [];`,
|
|
549
|
-
``,
|
|
550
|
-
` }`,
|
|
551
|
-
``,
|
|
552
|
-
` invalidate() : void {`,
|
|
553
|
-
``,
|
|
554
|
-
` let {tree} = this;`,
|
|
555
|
-
` let parent = <Node>tree.parentNode;`,
|
|
556
|
-
``,
|
|
557
|
-
` if (tree == null)`,
|
|
558
|
-
` return console.warn('invalidate(): '+` +
|
|
559
|
-
` 'Missing DOM tree!');`,
|
|
560
|
-
``,
|
|
561
|
-
` if (tree.parentNode == null)`,
|
|
562
|
-
` ${THROW_INVALIDATE_ERR}`,
|
|
563
|
-
``,
|
|
564
|
-
` parent.replaceChild(<Node>this.render(), tree) `,
|
|
565
|
-
``,
|
|
566
|
-
` }`,
|
|
567
|
-
``,
|
|
568
|
-
` render(): ${WML}.Content {`,
|
|
569
|
-
``,
|
|
570
|
-
` this.ids = {};`,
|
|
571
|
-
` this.widgets.forEach(w => w.removed());`,
|
|
572
|
-
` this.widgets = [];`,
|
|
573
|
-
` this.views = [];`,
|
|
574
|
-
` this.tree = <Node>this.template(this);`,
|
|
575
|
-
``,
|
|
576
|
-
` this.ids['root'] = (this.ids['root']) ?`,
|
|
577
|
-
` this.ids['root'] : `,
|
|
578
|
-
` this.tree;`,
|
|
579
|
-
``,
|
|
580
|
-
` this.widgets.forEach(w => w.rendered());`,
|
|
581
|
-
``,
|
|
582
|
-
` return this.tree;`,
|
|
583
|
-
``,
|
|
584
|
-
` }`,
|
|
585
|
-
``,
|
|
586
|
-
`}`
|
|
587
|
-
|
|
588
|
-
].join(eol(ctx))
|
|
589
|
-
|
|
590
|
-
}
|
|
310
|
+
return [
|
|
311
|
+
`export class ${id} ${typeParams} extends ${WML}.${VIEW_CLASS} {`,
|
|
312
|
+
``,
|
|
313
|
+
` constructor(${CONTEXT}: ${context} ${defaultContext}) {`,
|
|
314
|
+
``,
|
|
315
|
+
` super(${CONTEXT}, (${THIS}:${WML}.${FRAME_TYPE}) => {`,
|
|
316
|
+
``,
|
|
317
|
+
` ${instances}`,
|
|
318
|
+
``,
|
|
319
|
+
` ${THIS}.root(${template});`,
|
|
320
|
+
``,
|
|
321
|
+
``,
|
|
322
|
+
` });`,
|
|
323
|
+
``,
|
|
324
|
+
` }`,
|
|
325
|
+
``,
|
|
326
|
+
`}`,
|
|
327
|
+
].join(eol(ctx));
|
|
328
|
+
};
|
|
591
329
|
|
|
592
330
|
/**
|
|
593
|
-
* typeParameters2TS converts a list of typeParameters2TS into the a list of
|
|
331
|
+
* typeParameters2TS converts a list of typeParameters2TS into the a list of
|
|
594
332
|
* typescript typeParameters2TS.
|
|
595
333
|
*/
|
|
596
334
|
export const typeParameters2TS = (ns: ast.TypeParameter[]): string =>
|
|
597
|
-
|
|
335
|
+
ns.length === 0 ? "" : `<${ns.map(typeParameter2TS).join(",")}> `;
|
|
598
336
|
|
|
599
337
|
/**
|
|
600
338
|
* typeParameter2TS converts a type parameter into a typescript type parameter.
|
|
601
339
|
*/
|
|
602
340
|
export const typeParameter2TS = (n: ast.TypeParameter) =>
|
|
603
|
-
|
|
604
|
-
|
|
341
|
+
`${toPrim(identifierOrConstructor2TS(n.id))} ` +
|
|
342
|
+
`${n.constraint ? "extends " + type2TS(n.constraint) : ""} `;
|
|
605
343
|
|
|
606
344
|
/**
|
|
607
|
-
* type2TS
|
|
345
|
+
* type2TS
|
|
608
346
|
*/
|
|
609
347
|
export const type2TS = (n: ast.Type): TypeScript => {
|
|
348
|
+
if (n instanceof ast.ConstructorType) return constructorType2TS(n);
|
|
349
|
+
else if (n instanceof ast.RecordType) return recordType2Ts(n);
|
|
350
|
+
else if (n instanceof ast.ListType) return listType2TS(n);
|
|
351
|
+
else if (n instanceof ast.TupleType) return tupleType2TS(n);
|
|
352
|
+
else if (n instanceof ast.StringLiteral) return string2TS(n);
|
|
353
|
+
else if (n instanceof ast.NumberLiteral) return number2TS(n);
|
|
354
|
+
else if (n instanceof ast.BooleanLiteral) return boolean2TS(n);
|
|
355
|
+
else if (n instanceof ast.FunctionType) return functionType2TS(n);
|
|
610
356
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
else if (n instanceof ast.RecordType)
|
|
614
|
-
return recordType2Ts(n);
|
|
615
|
-
else if (n instanceof ast.ListType)
|
|
616
|
-
return listType2TS(n);
|
|
617
|
-
else if (n instanceof ast.TupleType)
|
|
618
|
-
return tupleType2TS(n);
|
|
619
|
-
else if (n instanceof ast.StringLiteral)
|
|
620
|
-
return string2TS(n);
|
|
621
|
-
else if (n instanceof ast.NumberLiteral)
|
|
622
|
-
return number2TS(n);
|
|
623
|
-
else if (n instanceof ast.BooleanLiteral)
|
|
624
|
-
return boolean2TS(n);
|
|
625
|
-
else if (n instanceof ast.FunctionType)
|
|
626
|
-
return functionType2TS(n);
|
|
627
|
-
|
|
628
|
-
return '<error>';
|
|
629
|
-
|
|
630
|
-
}
|
|
357
|
+
return "void";
|
|
358
|
+
};
|
|
631
359
|
|
|
632
360
|
/**
|
|
633
361
|
* constructorType2TS converts a ConstructorType into its id.
|
|
634
362
|
*
|
|
635
363
|
* If the node is generic, the type parameters will be generated as well.
|
|
636
364
|
*/
|
|
637
|
-
export const constructorType2TS =
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
let id = toPrim(identifierOrConstructor2TS(n.id));
|
|
365
|
+
export const constructorType2TS = (n: ast.ConstructorType) => {
|
|
366
|
+
let id = toPrim(identifierOrConstructor2TS(n.id));
|
|
641
367
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
368
|
+
return n.typeParameters.length > 0
|
|
369
|
+
? id + typeParameters2TS(n.typeParameters)
|
|
370
|
+
: id;
|
|
371
|
+
};
|
|
646
372
|
|
|
647
373
|
/**
|
|
648
374
|
* functionType2TS
|
|
649
375
|
*/
|
|
650
376
|
export const functionType2TS = (n: ast.FunctionType) => {
|
|
377
|
+
let params = n.parameters.map((t, k) => `$${k}:${type2TS(t)}`).join(",");
|
|
378
|
+
let ret = type2TS(n.returnType);
|
|
651
379
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
return `(${params}) => ${ret}`
|
|
656
|
-
|
|
657
|
-
}
|
|
380
|
+
return `(${params}) => ${ret}`;
|
|
381
|
+
};
|
|
658
382
|
|
|
659
383
|
/**
|
|
660
384
|
* listType2TS
|
|
661
385
|
*/
|
|
662
|
-
export const listType2TS = (n: ast.ListType) =>
|
|
663
|
-
`(${type2TS(n.elementType)})[]`;
|
|
386
|
+
export const listType2TS = (n: ast.ListType) => `(${type2TS(n.elementType)})[]`;
|
|
664
387
|
|
|
665
388
|
/**
|
|
666
389
|
* tupleType2TS
|
|
667
390
|
*/
|
|
668
391
|
export const tupleType2TS = (n: ast.TupleType) =>
|
|
669
|
-
|
|
392
|
+
`[${n.members.map(type2TS).join(",")}]`;
|
|
670
393
|
|
|
671
394
|
/**
|
|
672
395
|
* recordType2TS converts the RecordType node to the body of a TypeScript
|
|
673
396
|
* record interface.
|
|
674
397
|
*/
|
|
675
398
|
export const recordType2Ts = (n: ast.RecordType) =>
|
|
676
|
-
|
|
399
|
+
"{" + memberDeclarations2TS(n.members) + "}";
|
|
677
400
|
|
|
678
401
|
/**
|
|
679
402
|
* memberDeclarations2TS converts a list of MemberDeclarations to TypeScript.
|
|
@@ -682,36 +405,32 @@ export const recordType2Ts = (n: ast.RecordType) =>
|
|
|
682
405
|
* using the "<path1>.<path2>.<path3>" syntax occur as nested records.
|
|
683
406
|
*/
|
|
684
407
|
export const memberDeclarations2TS = (n: ast.MemberDeclaration[]) =>
|
|
685
|
-
|
|
408
|
+
typeMap2TS(expandTypeMap(typeMapFromMemberDecs(n)));
|
|
686
409
|
|
|
687
410
|
/**
|
|
688
411
|
* typeMapFromMemberDecs creates a TypeMap from a list of memberDeclarations.
|
|
689
412
|
*
|
|
690
413
|
* This works recursively and any RecordTypes encountered will be flattened.
|
|
691
414
|
*/
|
|
692
|
-
export const typeMapFromMemberDecs =
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
let paths = m.path.map(p => p.value);
|
|
697
|
-
|
|
698
|
-
if (m.kind instanceof ast.RecordType) {
|
|
699
|
-
|
|
700
|
-
return typeMapFromRecordType(m.kind, p, paths);
|
|
701
|
-
|
|
702
|
-
} else {
|
|
415
|
+
export const typeMapFromMemberDecs = (list: ast.MemberDeclaration[]) =>
|
|
416
|
+
list.reduce(
|
|
417
|
+
(p, m) => {
|
|
418
|
+
let paths = m.path.map((p) => p.value);
|
|
703
419
|
|
|
704
|
-
|
|
420
|
+
if (m.kind instanceof ast.RecordType) {
|
|
421
|
+
return typeMapFromRecordType(m.kind, p, paths);
|
|
422
|
+
} else {
|
|
423
|
+
let path = paths2String(paths);
|
|
705
424
|
|
|
706
|
-
|
|
425
|
+
path = m.optional ? `${path}?` : path;
|
|
707
426
|
|
|
708
|
-
|
|
427
|
+
p[path] = m.kind;
|
|
709
428
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
429
|
+
return p;
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
<TypeMap>{},
|
|
433
|
+
);
|
|
715
434
|
|
|
716
435
|
/**
|
|
717
436
|
* typeMapFromRecordType produces a map of node.Type instances from
|
|
@@ -719,136 +438,114 @@ export const typeMapFromMemberDecs =
|
|
|
719
438
|
*
|
|
720
439
|
* Any encountered RecordTypes will be flattened.
|
|
721
440
|
*/
|
|
722
|
-
export const typeMapFromRecordType =
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
return typeMapFromRecordType(m.kind, init, path);
|
|
731
|
-
|
|
732
|
-
} else {
|
|
733
|
-
|
|
734
|
-
p[paths2String(path)] = m.kind;
|
|
441
|
+
export const typeMapFromRecordType = (
|
|
442
|
+
n: ast.RecordType,
|
|
443
|
+
init: TypeMap,
|
|
444
|
+
prefix: string[],
|
|
445
|
+
): TypeMap =>
|
|
446
|
+
n.members.reduce((p, m) => {
|
|
447
|
+
let path = [...prefix, ...m.path.map((p) => p.value)];
|
|
735
448
|
|
|
736
|
-
|
|
449
|
+
if (m.kind instanceof ast.RecordType) {
|
|
450
|
+
return typeMapFromRecordType(m.kind, init, path);
|
|
451
|
+
} else {
|
|
452
|
+
p[paths2String(path)] = m.kind;
|
|
737
453
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
454
|
+
return p;
|
|
455
|
+
}
|
|
456
|
+
}, init);
|
|
741
457
|
|
|
742
|
-
const paths2String = (paths: string[]) => paths.join(
|
|
458
|
+
const paths2String = (paths: string[]) => paths.join(".");
|
|
743
459
|
|
|
744
460
|
/**
|
|
745
461
|
* expandTypeMap to an ExpandedTypeMap.
|
|
746
462
|
*/
|
|
747
463
|
export const expandTypeMap = (m: TypeMap): ExpandedTypeMap =>
|
|
748
|
-
|
|
749
|
-
|
|
464
|
+
reduce(m, <ExpandedTypeMap>{}, (p, c, k) =>
|
|
465
|
+
set<TypeOrMap, ExpandedTypeMap>(k, type2TS(c), p),
|
|
466
|
+
);
|
|
750
467
|
|
|
751
468
|
/**
|
|
752
469
|
* typeMap2TS converts a map of type values to TypeScript.
|
|
753
470
|
*/
|
|
754
471
|
export const typeMap2TS = (m: ExpandedTypeMap): TypeScript =>
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
return `${k} : ${t}`;
|
|
765
|
-
|
|
766
|
-
}
|
|
767
|
-
}).join(',\n');
|
|
472
|
+
mapTo(m, (t, k) => {
|
|
473
|
+
if (isRecord(t)) {
|
|
474
|
+
let key = isOptional(t) ? `${k}?` : `${k}`;
|
|
475
|
+
return `${key}: {${typeMap2TS(t)}}`;
|
|
476
|
+
} else {
|
|
477
|
+
return `${k} : ${t}`;
|
|
478
|
+
}
|
|
479
|
+
}).join(",\n");
|
|
768
480
|
|
|
769
481
|
const isOptional = (m: ExpandedTypeMap) =>
|
|
770
|
-
|
|
482
|
+
reduce(m, false, (p, _, k) => (p ? p : k.indexOf("?") > -1));
|
|
771
483
|
|
|
772
484
|
/**
|
|
773
485
|
* parameters2TS converts a list Parameter nodes into an parameter list
|
|
774
486
|
* (without parens).
|
|
775
487
|
*/
|
|
776
488
|
export const parameters2TS = (list: ast.Parameter[]) =>
|
|
777
|
-
|
|
489
|
+
list.map((p) => parameter2TS(p)).join(",");
|
|
778
490
|
|
|
779
491
|
/**
|
|
780
|
-
* parameter2TS
|
|
492
|
+
* parameter2TS
|
|
781
493
|
*/
|
|
782
494
|
export const parameter2TS = (n: ast.Parameter) => {
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
return untypedParameter2TS(n)
|
|
788
|
-
else
|
|
789
|
-
return '';
|
|
790
|
-
|
|
791
|
-
}
|
|
495
|
+
if (n instanceof ast.TypedParameter) return typedParameter2TS(n);
|
|
496
|
+
else if (n instanceof ast.UntypedParameter) return untypedParameter2TS(n);
|
|
497
|
+
else return "";
|
|
498
|
+
};
|
|
792
499
|
|
|
793
500
|
/**
|
|
794
|
-
* typedParameter2TS
|
|
501
|
+
* typedParameter2TS
|
|
795
502
|
*/
|
|
796
503
|
export const typedParameter2TS = (n: ast.TypedParameter) =>
|
|
797
|
-
|
|
504
|
+
`${identifier2TS(n.id)}: ${type2TS(n.hint)} `;
|
|
798
505
|
|
|
799
506
|
/**
|
|
800
|
-
* untypedParameter2TS
|
|
507
|
+
* untypedParameter2TS
|
|
801
508
|
*/
|
|
802
509
|
export const untypedParameter2TS = (n: ast.UntypedParameter) =>
|
|
803
|
-
|
|
510
|
+
`${identifier2TS(n.id)} `;
|
|
804
511
|
|
|
805
512
|
/**
|
|
806
513
|
* children2TS
|
|
807
514
|
*/
|
|
808
515
|
export const children2TS = (ctx: CodeGenerator, list: ast.Child[]) =>
|
|
809
|
-
|
|
810
|
-
${list.map(l => child2TS(ctx, l)).join(
|
|
516
|
+
`[${ctx.options.EOL}
|
|
517
|
+
${list.map((l) => child2TS(ctx, l)).join("," + ctx.options.EOL)}
|
|
811
518
|
]`;
|
|
812
519
|
|
|
813
520
|
/**
|
|
814
521
|
* child2TS converts children to typescript.
|
|
815
522
|
*/
|
|
816
523
|
export const child2TS = (ctx: CodeGenerator, n: ast.Child): string => {
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
else if (n instanceof ast.UnqualifiedConstructor)
|
|
837
|
-
return unqualifiedConstructor2TS(n);
|
|
838
|
-
else if (n instanceof ast.UnqualifiedIdentifier)
|
|
839
|
-
return unqualifiedIdentifier2TS(n);
|
|
840
|
-
else if (n instanceof ast.QualifiedIdentifier)
|
|
841
|
-
return qualifiedIdentifier2TS(n);
|
|
842
|
-
else
|
|
843
|
-
return '';
|
|
844
|
-
|
|
845
|
-
}
|
|
524
|
+
if (n instanceof ast.Node || n instanceof ast.Widget) return tag2TS(ctx, n);
|
|
525
|
+
else if (n instanceof ast.Interpolation) return interpolation2TS(ctx, n);
|
|
526
|
+
else if (n instanceof ast.IfStatement) return ifStatement2TS(ctx, n);
|
|
527
|
+
else if (n instanceof ast.ForInStatement) return forInStatement2TS(ctx, n);
|
|
528
|
+
else if (n instanceof ast.ForOfStatement) return forOfStatement2TS(ctx, n);
|
|
529
|
+
else if (n instanceof ast.ForFromStatement)
|
|
530
|
+
return forFromStatement2TS(ctx, n);
|
|
531
|
+
else if (n instanceof ast.Characters) return characters2TS(n);
|
|
532
|
+
else if (n instanceof ast.ContextProperty) return contextProperty2TS(n);
|
|
533
|
+
else if (n instanceof ast.QualifiedConstructor)
|
|
534
|
+
return qualifiedConstructor2TS(n);
|
|
535
|
+
else if (n instanceof ast.UnqualifiedConstructor)
|
|
536
|
+
return unqualifiedConstructor2TS(n);
|
|
537
|
+
else if (n instanceof ast.UnqualifiedIdentifier)
|
|
538
|
+
return unqualifiedIdentifier2TS(n);
|
|
539
|
+
else if (n instanceof ast.QualifiedIdentifier)
|
|
540
|
+
return qualifiedIdentifier2TS(n);
|
|
541
|
+
else return "";
|
|
542
|
+
};
|
|
846
543
|
|
|
847
544
|
/**
|
|
848
545
|
* tag2TS converts a tag to typescript.
|
|
849
546
|
*/
|
|
850
547
|
export const tag2TS = (ctx: CodeGenerator, n: ast.Tag) =>
|
|
851
|
-
|
|
548
|
+
n instanceof ast.Widget ? widget2TS(ctx, n) : node2TS(ctx, n);
|
|
852
549
|
|
|
853
550
|
/**
|
|
854
551
|
* widget2TS converts a Widget node into its typescript representation.
|
|
@@ -856,16 +553,16 @@ export const tag2TS = (ctx: CodeGenerator, n: ast.Tag) =>
|
|
|
856
553
|
* This is simply a call to the View's widget method.
|
|
857
554
|
*/
|
|
858
555
|
export const widget2TS = (ctx: CodeGenerator, n: ast.Widget) => {
|
|
556
|
+
let name = constructor2TS(n.open);
|
|
557
|
+
let typeParams = typeArgs2TS(n.typeArgs);
|
|
558
|
+
let attrs = attrs2String(ctx, n.attributes);
|
|
559
|
+
let childs = children2TS(ctx, n.children);
|
|
859
560
|
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
return `${THIS}.widget(new ${name}${typeParams}(${attrs}, ${childs}),` +
|
|
866
|
-
`<${WML}.Attrs>${attrs})`;
|
|
867
|
-
|
|
868
|
-
}
|
|
561
|
+
return (
|
|
562
|
+
`${THIS}.widget(new ${name}${typeParams}(${attrs}, ${childs}),` +
|
|
563
|
+
`<${WML}.Attrs>${attrs})`
|
|
564
|
+
);
|
|
565
|
+
};
|
|
869
566
|
|
|
870
567
|
/**
|
|
871
568
|
* node2TS converts a Node into its typescript representation.
|
|
@@ -873,388 +570,387 @@ export const widget2TS = (ctx: CodeGenerator, n: ast.Widget) => {
|
|
|
873
570
|
* This is simply a call to the View's node method.
|
|
874
571
|
*/
|
|
875
572
|
export const node2TS = (ctx: CodeGenerator, n: ast.Node) => {
|
|
573
|
+
let name = identifier2TS(n.open);
|
|
574
|
+
let attrs = attrs2String(ctx, n.attributes);
|
|
575
|
+
let childs = children2TS(ctx, n.children);
|
|
876
576
|
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
let childs = children2TS(ctx, n.children);
|
|
880
|
-
|
|
881
|
-
return `${THIS}.node('${name}', <${WML}.Attrs>${attrs}, ${childs})`;
|
|
882
|
-
|
|
883
|
-
}
|
|
577
|
+
return `${THIS}.node('${name}', <${WML}.Attrs>${attrs}, ${childs})`;
|
|
578
|
+
};
|
|
884
579
|
|
|
885
580
|
/**
|
|
886
|
-
* attribute2Value
|
|
581
|
+
* attribute2Value
|
|
887
582
|
*/
|
|
888
583
|
export const attribute2TS = (ctx: CodeGenerator, n: ast.Attribute) =>
|
|
889
|
-
|
|
584
|
+
`${attributeName2TS(ctx, n)} : ${attributeValue2TS(ctx, n)} `;
|
|
890
585
|
|
|
891
586
|
/**
|
|
892
587
|
* attributeValue2TS
|
|
893
588
|
*/
|
|
894
|
-
export const attributeValue2TS =
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
literal2TS(ctx, n.value);
|
|
589
|
+
export const attributeValue2TS = (ctx: CodeGenerator, n: ast.Attribute) =>
|
|
590
|
+
n.value instanceof ast.Interpolation
|
|
591
|
+
? interpolation2TS(ctx, n.value)
|
|
592
|
+
: literal2TS(ctx, n.value);
|
|
899
593
|
|
|
900
594
|
/**
|
|
901
595
|
* attributeName2TS
|
|
902
596
|
*/
|
|
903
597
|
export const attributeName2TS = (_: CodeGenerator, n: ast.Attribute) =>
|
|
904
|
-
|
|
598
|
+
`'${unqualifiedIdentifier2TS(n.name)}'`;
|
|
905
599
|
|
|
906
600
|
/**
|
|
907
|
-
* attrs2String
|
|
601
|
+
* attrs2String
|
|
908
602
|
*/
|
|
909
603
|
export const attrs2String = (ctx: CodeGenerator, attrs: ast.Attribute[]) => {
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
604
|
+
// Check for the special wml:attrs attribute.
|
|
605
|
+
|
|
606
|
+
let mallAttrs = find(
|
|
607
|
+
attrs,
|
|
608
|
+
(attr) => attr.namespace.value === "wml" && attr.name.value === "attrs",
|
|
609
|
+
);
|
|
610
|
+
|
|
611
|
+
if (mallAttrs.isJust()) return attributeValue2TS(ctx, mallAttrs.get());
|
|
612
|
+
|
|
613
|
+
let [nns, ns] = partition(attrs, (a) => a.namespace.value === "");
|
|
614
|
+
|
|
615
|
+
let nso = ns.reduce(
|
|
616
|
+
(p, n) =>
|
|
617
|
+
merge(p, {
|
|
618
|
+
[n.namespace.value]: (p[n.namespace.value] || []).concat(
|
|
619
|
+
attribute2TS(ctx, n),
|
|
620
|
+
),
|
|
621
|
+
}),
|
|
622
|
+
<{ [key: string]: string[] }>{},
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
return _attrs2String(
|
|
626
|
+
nns.reduce(
|
|
627
|
+
(p, n) =>
|
|
628
|
+
merge(p, {
|
|
629
|
+
[attributeName2TS(ctx, n)]: attributeValue2TS(ctx, n),
|
|
630
|
+
}),
|
|
631
|
+
<{ [key: string]: string | string[] }>nso,
|
|
632
|
+
),
|
|
633
|
+
);
|
|
634
|
+
};
|
|
934
635
|
|
|
935
636
|
const _attrs2String = (attrs: { [key: string]: string | string[] }) =>
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
637
|
+
"{" +
|
|
638
|
+
Object.keys(attrs).map((name) =>
|
|
639
|
+
Array.isArray(attrs[name])
|
|
640
|
+
? `${name} : { ${(<string[]>attrs[name]).join(",")} }`
|
|
641
|
+
: `${name}: ${attrs[name]}`,
|
|
642
|
+
) +
|
|
643
|
+
"}";
|
|
942
644
|
|
|
943
645
|
/**
|
|
944
|
-
* interpolation2TS
|
|
646
|
+
* interpolation2TS
|
|
945
647
|
*/
|
|
946
648
|
export const interpolation2TS = (ctx: CodeGenerator, n: ast.Interpolation) =>
|
|
947
|
-
|
|
948
|
-
|
|
649
|
+
n.filters.reduce(
|
|
650
|
+
(p, c) => `${expression2TS(ctx, c)} (${p})`,
|
|
651
|
+
expression2TS(ctx, n.expression),
|
|
652
|
+
);
|
|
949
653
|
|
|
950
654
|
/**
|
|
951
655
|
* ifStatementTS converts an IfStatement to its typescript representation.
|
|
952
656
|
*/
|
|
953
|
-
export const ifStatement2TS =
|
|
954
|
-
|
|
657
|
+
export const ifStatement2TS = (
|
|
658
|
+
ctx: CodeGenerator,
|
|
659
|
+
n: ast.IfStatement,
|
|
660
|
+
): TypeScript => {
|
|
661
|
+
let condition = expression2TS(ctx, n.condition);
|
|
662
|
+
let conseq = children2TS(ctx, n.then);
|
|
955
663
|
|
|
956
|
-
|
|
957
|
-
|
|
664
|
+
let alt =
|
|
665
|
+
n.elseClause instanceof ast.ElseIfClause
|
|
666
|
+
? `[${ifStatement2TS(ctx, n.elseClause)}]`
|
|
667
|
+
: n.elseClause instanceof ast.ElseClause
|
|
668
|
+
? children2TS(ctx, n.elseClause.children)
|
|
669
|
+
: "[]";
|
|
958
670
|
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
return [
|
|
966
|
-
`...((${condition}) ?`,
|
|
967
|
-
`(()=>(${conseq}))() :`,
|
|
968
|
-
`(()=>(${alt}))())`
|
|
969
|
-
].join(ctx.options.EOL);
|
|
970
|
-
|
|
971
|
-
}
|
|
671
|
+
return [
|
|
672
|
+
`...((${condition}) ?`,
|
|
673
|
+
`(()=>(${conseq}))() :`,
|
|
674
|
+
`(()=>(${alt}))())`,
|
|
675
|
+
].join(ctx.options.EOL);
|
|
676
|
+
};
|
|
972
677
|
|
|
973
678
|
/**
|
|
974
679
|
* forInStatement2TS converts a ForInStatement to its typescript representation.
|
|
975
680
|
*/
|
|
976
|
-
export const forInStatement2TS = (
|
|
681
|
+
export const forInStatement2TS = (
|
|
682
|
+
ctx: CodeGenerator,
|
|
683
|
+
n: ast.ForInStatement,
|
|
684
|
+
) => {
|
|
685
|
+
let expr = expression2TS(ctx, n.expression);
|
|
977
686
|
|
|
978
|
-
|
|
687
|
+
let value = parameter2TS(n.variables[0]);
|
|
979
688
|
|
|
980
|
-
|
|
689
|
+
let key = n.variables.length > 1 ? parameter2TS(n.variables[1]) : "_$$i";
|
|
981
690
|
|
|
982
|
-
|
|
691
|
+
let all = n.variables.length > 2 ? parameter2TS(n.variables[2]) : "_$$all";
|
|
983
692
|
|
|
984
|
-
|
|
693
|
+
let body = children2TS(ctx, n.body);
|
|
985
694
|
|
|
986
|
-
|
|
695
|
+
let alt = n.otherwise.length > 0 ? children2TS(ctx, n.otherwise) : "[]";
|
|
987
696
|
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
].join(ctx.options.EOL);
|
|
995
|
-
|
|
996
|
-
}
|
|
697
|
+
return [
|
|
698
|
+
`...${FOR_IN} (${expr}, (${value}, ${key}, ${all})=> `,
|
|
699
|
+
`(${body}), `,
|
|
700
|
+
`()=> (${alt}))`,
|
|
701
|
+
].join(ctx.options.EOL);
|
|
702
|
+
};
|
|
997
703
|
|
|
998
704
|
/**
|
|
999
705
|
* forOfStatement2TS
|
|
1000
706
|
*/
|
|
1001
|
-
export const forOfStatement2TS = (
|
|
707
|
+
export const forOfStatement2TS = (
|
|
708
|
+
ctx: CodeGenerator,
|
|
709
|
+
n: ast.ForOfStatement,
|
|
710
|
+
) => {
|
|
711
|
+
let expr = expression2TS(ctx, n.expression);
|
|
1002
712
|
|
|
1003
|
-
|
|
713
|
+
let value = parameter2TS(n.variables[0]);
|
|
1004
714
|
|
|
1005
|
-
|
|
715
|
+
let key = n.variables.length > 1 ? parameter2TS(n.variables[1]) : "_$$k";
|
|
1006
716
|
|
|
1007
|
-
|
|
717
|
+
let all = n.variables.length > 2 ? parameter2TS(n.variables[2]) : "_$$all";
|
|
1008
718
|
|
|
1009
|
-
|
|
719
|
+
let body = children2TS(ctx, n.body);
|
|
1010
720
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
let alt = n.otherwise.length > 0 ? children2TS(ctx, n.otherwise) : '[]';
|
|
1014
|
-
|
|
1015
|
-
return [
|
|
1016
|
-
`...${FOR_OF} (${expr}, (${value}, ${key}, ${all}) => `,
|
|
1017
|
-
` (${body}), `,
|
|
1018
|
-
` ()=> (${alt}))`
|
|
1019
|
-
].join(eol(ctx));
|
|
721
|
+
let alt = n.otherwise.length > 0 ? children2TS(ctx, n.otherwise) : "[]";
|
|
1020
722
|
|
|
1021
|
-
|
|
723
|
+
return [
|
|
724
|
+
`...${FOR_OF} (${expr}, (${value}, ${key}, ${all}) => `,
|
|
725
|
+
` (${body}), `,
|
|
726
|
+
` ()=> (${alt}))`,
|
|
727
|
+
].join(eol(ctx));
|
|
728
|
+
};
|
|
1022
729
|
|
|
1023
730
|
/**
|
|
1024
731
|
* forFromStatement2TS
|
|
1025
732
|
*/
|
|
1026
|
-
export const forFromStatement2TS =
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
733
|
+
export const forFromStatement2TS = (
|
|
734
|
+
ctx: CodeGenerator,
|
|
735
|
+
node: ast.ForFromStatement,
|
|
736
|
+
) => {
|
|
737
|
+
let value = parameter2TS(node.variable);
|
|
1030
738
|
|
|
1031
|
-
|
|
739
|
+
let start = expression2TS(ctx, node.start);
|
|
1032
740
|
|
|
1033
|
-
|
|
741
|
+
let end = expression2TS(ctx, node.end);
|
|
1034
742
|
|
|
1035
|
-
|
|
743
|
+
let body = children2TS(ctx, node.body);
|
|
1036
744
|
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
}
|
|
745
|
+
return [
|
|
746
|
+
`...(function forFrom() {`,
|
|
747
|
+
` let result:${WML}.Content[] = [];`,
|
|
748
|
+
` for(let ${value}:number=${start}; ${value}<=${end}; ${value}++)`,
|
|
749
|
+
` result.push(`,
|
|
750
|
+
` ...${body}`,
|
|
751
|
+
` );`,
|
|
752
|
+
` return result;`,
|
|
753
|
+
`})()`,
|
|
754
|
+
].join(eol(ctx));
|
|
755
|
+
};
|
|
1049
756
|
|
|
1050
757
|
/**
|
|
1051
758
|
* characters2TS converts character text to a typescript string.
|
|
1052
759
|
*/
|
|
1053
760
|
export const characters2TS = (n: ast.Characters) =>
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
const breakLines = (str: string) => str.split(
|
|
1057
|
-
|
|
1058
|
-
/**
|
|
1059
|
-
* expression2TS
|
|
1060
|
-
*/
|
|
1061
|
-
export const expression2TS = (
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
`${THIS}.registerView(${expression2TS(ctx, n.expression)}).render()`;
|
|
1156
|
-
|
|
1157
|
-
/**
|
|
1158
|
-
* funApplication2TS
|
|
761
|
+
`${DOCUMENT}.createTextNode('${breakLines(n.value)}')`;
|
|
762
|
+
|
|
763
|
+
const breakLines = (str: string) => str.split("\n").join("\\u000a");
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* expression2TS
|
|
767
|
+
*/
|
|
768
|
+
export const expression2TS = (
|
|
769
|
+
ctx: CodeGenerator,
|
|
770
|
+
n: ast.Expression,
|
|
771
|
+
): string => {
|
|
772
|
+
if (n instanceof ast.IfThenExpression) return ifThenExpression2TS(ctx, n);
|
|
773
|
+
else if (n instanceof ast.BinaryExpression)
|
|
774
|
+
return binaryExpression2TS(ctx, n);
|
|
775
|
+
else if (n instanceof ast.UnaryExpression) return unaryExpression2TS(ctx, n);
|
|
776
|
+
else if (n instanceof ast.ViewConstruction)
|
|
777
|
+
return viewConstruction2TS(ctx, n);
|
|
778
|
+
else if (n instanceof ast.FunApplication) return funApplication2TS(ctx, n);
|
|
779
|
+
else if (n instanceof ast.ConstructExpression)
|
|
780
|
+
return constructExpression2TS(ctx, n);
|
|
781
|
+
else if (n instanceof ast.CallExpression) return callExpression2TS(ctx, n);
|
|
782
|
+
else if (n instanceof ast.MemberExpression)
|
|
783
|
+
return memberExpression2TS(ctx, n);
|
|
784
|
+
else if (n instanceof ast.FunctionExpression)
|
|
785
|
+
return functionExpression2TS(ctx, n);
|
|
786
|
+
else if (n instanceof ast.Record) return record2TS(ctx, n);
|
|
787
|
+
else if (n instanceof ast.List) return list2TS(ctx, n);
|
|
788
|
+
else if (n instanceof ast.BooleanLiteral) return boolean2TS(n);
|
|
789
|
+
else if (n instanceof ast.NumberLiteral) return number2TS(n);
|
|
790
|
+
else if (n instanceof ast.StringLiteral) return string2TS(n);
|
|
791
|
+
else if (n instanceof ast.ContextProperty) return contextProperty2TS(n);
|
|
792
|
+
else if (n instanceof ast.QualifiedConstructor)
|
|
793
|
+
return qualifiedConstructor2TS(n);
|
|
794
|
+
else if (n instanceof ast.UnqualifiedConstructor)
|
|
795
|
+
return unqualifiedConstructor2TS(n);
|
|
796
|
+
else if (n instanceof ast.UnqualifiedIdentifier)
|
|
797
|
+
return unqualifiedIdentifier2TS(n);
|
|
798
|
+
else if (n instanceof ast.QualifiedIdentifier)
|
|
799
|
+
return qualifiedIdentifier2TS(n);
|
|
800
|
+
else if (n instanceof ast.ContextVariable) return contextVariable2TS(n);
|
|
801
|
+
else return "";
|
|
802
|
+
};
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* ifThenExpression2TS
|
|
806
|
+
*/
|
|
807
|
+
export const ifThenExpression2TS = (
|
|
808
|
+
ctx: CodeGenerator,
|
|
809
|
+
n: ast.IfThenExpression,
|
|
810
|
+
) => {
|
|
811
|
+
let condition = expression2TS(ctx, n.condition);
|
|
812
|
+
let conseq = expression2TS(ctx, n.iftrue);
|
|
813
|
+
let alt = expression2TS(ctx, n.iffalse);
|
|
814
|
+
|
|
815
|
+
return `(${condition}) ? ${conseq} : ${alt}`;
|
|
816
|
+
};
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* binaryExpression2TS
|
|
820
|
+
*/
|
|
821
|
+
export const binaryExpression2TS = (
|
|
822
|
+
ctx: CodeGenerator,
|
|
823
|
+
n: ast.BinaryExpression,
|
|
824
|
+
) => {
|
|
825
|
+
let left = expression2TS(ctx, n.left);
|
|
826
|
+
|
|
827
|
+
let right =
|
|
828
|
+
n.operator === "as"
|
|
829
|
+
? type2TS(<ast.Type>n.right)
|
|
830
|
+
: expression2TS(ctx, n.right);
|
|
831
|
+
|
|
832
|
+
let op = operators.hasOwnProperty(n.operator)
|
|
833
|
+
? operators[n.operator]
|
|
834
|
+
: n.operator;
|
|
835
|
+
|
|
836
|
+
return n.operator === "as"
|
|
837
|
+
? `<${right}>(${left})`
|
|
838
|
+
: `(${left} ${op} ${right})`;
|
|
839
|
+
};
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* unaryExpression2TS
|
|
843
|
+
*/
|
|
844
|
+
export const unaryExpression2TS = (
|
|
845
|
+
ctx: CodeGenerator,
|
|
846
|
+
n: ast.UnaryExpression,
|
|
847
|
+
) => {
|
|
848
|
+
let expr = expression2TS(ctx, n.expression);
|
|
849
|
+
return `${n.operator}(${expr})`;
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* viewConstruction2TS
|
|
854
|
+
*/
|
|
855
|
+
export const viewConstruction2TS = (
|
|
856
|
+
ctx: CodeGenerator,
|
|
857
|
+
n: ast.ViewConstruction,
|
|
858
|
+
) => `${THIS}.view(${expression2TS(ctx, n.expression)})`;
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* funApplication2TS
|
|
1159
862
|
*/
|
|
1160
863
|
export const funApplication2TS = (ctx: CodeGenerator, n: ast.FunApplication) =>
|
|
1161
|
-
|
|
1162
|
-
|
|
864
|
+
`${expression2TS(ctx, n.target)}${typeArgs2TS(n.typeArgs)} ` +
|
|
865
|
+
`(${args2TS(ctx, n.args)})(${THIS})`;
|
|
1163
866
|
|
|
1164
867
|
/**
|
|
1165
|
-
* constructExpression2TS
|
|
868
|
+
* constructExpression2TS
|
|
1166
869
|
*/
|
|
1167
|
-
export const constructExpression2TS =
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
870
|
+
export const constructExpression2TS = (
|
|
871
|
+
ctx: CodeGenerator,
|
|
872
|
+
n: ast.ConstructExpression,
|
|
873
|
+
) => {
|
|
874
|
+
let cons = constructor2TS(n.cons);
|
|
1171
875
|
|
|
1172
|
-
|
|
876
|
+
let consOriginal = `${cons[0].toUpperCase()}${cons.slice(1)}`;
|
|
1173
877
|
|
|
1174
|
-
|
|
878
|
+
let typeArgs = typeArgs2TS(n.typeArgs);
|
|
1175
879
|
|
|
1176
|
-
|
|
880
|
+
let args = args2TS(ctx, n.args);
|
|
1177
881
|
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
`new ${cons}${typeArgs}(${args})`;
|
|
1183
|
-
|
|
1184
|
-
}
|
|
882
|
+
return contains(casters, consOriginal)
|
|
883
|
+
? `${consOriginal}${typeArgs}(${args})`
|
|
884
|
+
: `new ${cons}${typeArgs}(${args})`;
|
|
885
|
+
};
|
|
1185
886
|
|
|
1186
887
|
/**
|
|
1187
|
-
* callExpression2TS
|
|
888
|
+
* callExpression2TS
|
|
1188
889
|
*/
|
|
1189
|
-
export const callExpression2TS = (
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
890
|
+
export const callExpression2TS = (
|
|
891
|
+
ctx: CodeGenerator,
|
|
892
|
+
n: ast.CallExpression,
|
|
893
|
+
) => {
|
|
894
|
+
let target = expression2TS(ctx, n.target);
|
|
895
|
+
let typeArgs = typeArgs2TS(n.typeArgs);
|
|
896
|
+
let args = args2TS(ctx, n.args);
|
|
1194
897
|
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
}
|
|
898
|
+
return `${target}${typeArgs}(${args})`;
|
|
899
|
+
};
|
|
1198
900
|
|
|
1199
901
|
/**
|
|
1200
|
-
* typeArgs2TS
|
|
902
|
+
* typeArgs2TS
|
|
1201
903
|
*/
|
|
1202
904
|
export const typeArgs2TS = (ns: ast.Type[]) =>
|
|
1203
|
-
|
|
905
|
+
empty(ns) ? "" : `<${ns.map(type2TS).join(",")}>`;
|
|
1204
906
|
|
|
1205
907
|
/**
|
|
1206
908
|
* args2TS converts a list of arguments to a typescript argument tupple.
|
|
1207
909
|
*/
|
|
1208
910
|
export const args2TS = (ctx: CodeGenerator, ns: ast.Expression[]) =>
|
|
1209
|
-
|
|
911
|
+
ns.length === 0 ? "" : ns.map((e) => expression2TS(ctx, e)).join(",");
|
|
1210
912
|
|
|
1211
913
|
/**
|
|
1212
|
-
* memberExpression2TS
|
|
914
|
+
* memberExpression2TS
|
|
1213
915
|
*/
|
|
1214
|
-
export const memberExpression2TS =
|
|
1215
|
-
|
|
1216
|
-
|
|
916
|
+
export const memberExpression2TS = (
|
|
917
|
+
ctx: CodeGenerator,
|
|
918
|
+
n: ast.MemberExpression,
|
|
919
|
+
) => {
|
|
920
|
+
let target = expression2TS(ctx, n.head);
|
|
1217
921
|
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
922
|
+
return n.tail instanceof ast.StringLiteral
|
|
923
|
+
? `${target}[${string2TS(n.tail)}]`
|
|
924
|
+
: `${target}.${expression2TS(ctx, n.tail)}`;
|
|
925
|
+
};
|
|
1222
926
|
|
|
1223
927
|
/**
|
|
1224
928
|
* functionExpression2TS
|
|
1225
929
|
*/
|
|
1226
|
-
export const functionExpression2TS =
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
return `(${params}) => ${body}`;
|
|
930
|
+
export const functionExpression2TS = (
|
|
931
|
+
ctx: CodeGenerator,
|
|
932
|
+
n: ast.FunctionExpression,
|
|
933
|
+
) => {
|
|
934
|
+
let params = n.parameters.map(parameter2TS).join(",");
|
|
935
|
+
let body = expression2TS(ctx, n.body);
|
|
1233
936
|
|
|
1234
|
-
|
|
937
|
+
return `(${params}) => ${body}`;
|
|
938
|
+
};
|
|
1235
939
|
|
|
1236
940
|
/**
|
|
1237
|
-
* literal2TS
|
|
941
|
+
* literal2TS
|
|
1238
942
|
*/
|
|
1239
943
|
export const literal2TS = (ctx: CodeGenerator, n: ast.Literal) => {
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
else if (n instanceof ast.Record)
|
|
1248
|
-
return record2TS(ctx, n);
|
|
1249
|
-
else if (n instanceof ast.List)
|
|
1250
|
-
return list2TS(ctx, n);
|
|
1251
|
-
else
|
|
1252
|
-
return '';
|
|
1253
|
-
|
|
1254
|
-
}
|
|
944
|
+
if (n instanceof ast.BooleanLiteral) return boolean2TS(n);
|
|
945
|
+
else if (n instanceof ast.StringLiteral) return string2TS(n);
|
|
946
|
+
else if (n instanceof ast.NumberLiteral) return number2TS(n);
|
|
947
|
+
else if (n instanceof ast.Record) return record2TS(ctx, n);
|
|
948
|
+
else if (n instanceof ast.List) return list2TS(ctx, n);
|
|
949
|
+
else return "";
|
|
950
|
+
};
|
|
1255
951
|
|
|
1256
952
|
/**
|
|
1257
|
-
* boolean2TS
|
|
953
|
+
* boolean2TS
|
|
1258
954
|
*/
|
|
1259
955
|
export const boolean2TS = (n: ast.BooleanLiteral) => `${n.value} `;
|
|
1260
956
|
|
|
@@ -1262,10 +958,13 @@ export const boolean2TS = (n: ast.BooleanLiteral) => `${n.value} `;
|
|
|
1262
958
|
* string2TS
|
|
1263
959
|
*/
|
|
1264
960
|
export const string2TS = (n: ast.StringLiteral) =>
|
|
1265
|
-
|
|
961
|
+
n.value
|
|
962
|
+
.split("\n")
|
|
963
|
+
.map((str) => `"${str}"`)
|
|
964
|
+
.join("+");
|
|
1266
965
|
|
|
1267
966
|
/**
|
|
1268
|
-
* number2TS
|
|
967
|
+
* number2TS
|
|
1269
968
|
*/
|
|
1270
969
|
export const number2TS = (n: ast.NumberLiteral) => `${parseFloat(n.value)}`;
|
|
1271
970
|
|
|
@@ -1273,119 +972,111 @@ export const number2TS = (n: ast.NumberLiteral) => `${parseFloat(n.value)}`;
|
|
|
1273
972
|
* record2TS
|
|
1274
973
|
*/
|
|
1275
974
|
export const record2TS = (ctx: CodeGenerator, n: ast.Record) =>
|
|
1276
|
-
|
|
1277
|
-
${n.properties.map(p => property2TS(ctx, p)).join(
|
|
975
|
+
`{${ctx.options.EOL}
|
|
976
|
+
${n.properties.map((p) => property2TS(ctx, p)).join("," + ctx.options.EOL)}
|
|
1278
977
|
}`;
|
|
1279
978
|
|
|
1280
979
|
/**
|
|
1281
980
|
* list2TS
|
|
1282
981
|
*/
|
|
1283
982
|
export const list2TS = (ctx: CodeGenerator, n: ast.List) => {
|
|
983
|
+
let mems = n.members.map((e) => expression2TS(ctx, e));
|
|
1284
984
|
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
return `[${ctx.options.EOL}
|
|
1288
|
-
${mems.join(',' + ctx.options.EOL)}
|
|
985
|
+
return `[${ctx.options.EOL}
|
|
986
|
+
${mems.join("," + ctx.options.EOL)}
|
|
1289
987
|
]`;
|
|
1290
|
-
|
|
1291
|
-
}
|
|
988
|
+
};
|
|
1292
989
|
|
|
1293
990
|
/**
|
|
1294
991
|
* property2TS
|
|
1295
992
|
*/
|
|
1296
993
|
export const property2TS = (ctx: CodeGenerator, n: ast.Property) =>
|
|
1297
|
-
|
|
994
|
+
`'${key2TS(n.key)}' : ${expression2TS(ctx, n.value)}`;
|
|
1298
995
|
|
|
1299
996
|
/**
|
|
1300
|
-
* key2TS
|
|
997
|
+
* key2TS
|
|
1301
998
|
*/
|
|
1302
999
|
export const key2TS = (n: ast.StringLiteral | ast.UnqualifiedIdentifier) =>
|
|
1303
|
-
|
|
1000
|
+
n instanceof ast.StringLiteral ? string2TS(n) : identifier2TS(n);
|
|
1304
1001
|
|
|
1305
1002
|
/**
|
|
1306
|
-
* contextProperty2TS
|
|
1003
|
+
* contextProperty2TS
|
|
1307
1004
|
*/
|
|
1308
1005
|
export const contextProperty2TS = (n: ast.ContextProperty) => {
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1006
|
+
let member =
|
|
1007
|
+
n.member instanceof ast.StringLiteral
|
|
1008
|
+
? n.member.value
|
|
1009
|
+
: identifier2TS(n.member);
|
|
1312
1010
|
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
}
|
|
1011
|
+
return `${CONTEXT}.${member}`;
|
|
1012
|
+
};
|
|
1316
1013
|
|
|
1317
1014
|
/**
|
|
1318
|
-
* contextVariable2TS
|
|
1015
|
+
* contextVariable2TS
|
|
1319
1016
|
*/
|
|
1320
1017
|
export const contextVariable2TS = (_: ast.ContextVariable) => `${CONTEXT}`;
|
|
1321
1018
|
|
|
1322
1019
|
/**
|
|
1323
1020
|
* identifierOrConstructor2TS
|
|
1324
1021
|
*/
|
|
1325
|
-
export const identifierOrConstructor2TS =
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1022
|
+
export const identifierOrConstructor2TS = (
|
|
1023
|
+
n: ast.Identifier | ast.Constructor,
|
|
1024
|
+
) => {
|
|
1025
|
+
if (
|
|
1026
|
+
n instanceof ast.UnqualifiedIdentifier ||
|
|
1027
|
+
n instanceof ast.QualifiedIdentifier
|
|
1028
|
+
)
|
|
1029
|
+
return identifier2TS(n);
|
|
1030
|
+
else if (
|
|
1031
|
+
n instanceof ast.UnqualifiedConstructor ||
|
|
1032
|
+
n instanceof ast.QualifiedConstructor
|
|
1033
|
+
)
|
|
1034
|
+
return constructor2TS(n);
|
|
1035
|
+
else return "";
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
/**
|
|
1039
|
+
* constructor2TS
|
|
1341
1040
|
*/
|
|
1342
1041
|
export const constructor2TS = (n: ast.Constructor) => {
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
else
|
|
1349
|
-
return '';
|
|
1350
|
-
|
|
1351
|
-
}
|
|
1042
|
+
if (n instanceof ast.QualifiedConstructor) return qualifiedConstructor2TS(n);
|
|
1043
|
+
else if (n instanceof ast.UnqualifiedConstructor)
|
|
1044
|
+
return unqualifiedConstructor2TS(n);
|
|
1045
|
+
else return "";
|
|
1046
|
+
};
|
|
1352
1047
|
|
|
1353
1048
|
/**
|
|
1354
|
-
* unqualifiedConstructor2TS
|
|
1049
|
+
* unqualifiedConstructor2TS
|
|
1355
1050
|
*/
|
|
1356
1051
|
export const unqualifiedConstructor2TS = (n: ast.UnqualifiedConstructor) =>
|
|
1357
|
-
|
|
1052
|
+
toPrim(n.value);
|
|
1358
1053
|
|
|
1359
1054
|
/**
|
|
1360
1055
|
* qualifiedConstructor
|
|
1361
1056
|
*/
|
|
1362
1057
|
export const qualifiedConstructor2TS = (n: ast.QualifiedConstructor) =>
|
|
1363
|
-
|
|
1058
|
+
`${n.qualifier}.${n.member}`;
|
|
1364
1059
|
|
|
1365
1060
|
/**
|
|
1366
1061
|
* identifier2TS
|
|
1367
1062
|
*/
|
|
1368
1063
|
export const identifier2TS = (n: ast.Identifier) => {
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
else
|
|
1375
|
-
return ''
|
|
1376
|
-
|
|
1377
|
-
}
|
|
1064
|
+
if (n instanceof ast.QualifiedIdentifier) return qualifiedIdentifier2TS(n);
|
|
1065
|
+
else if (n instanceof ast.UnqualifiedIdentifier)
|
|
1066
|
+
return unqualifiedIdentifier2TS(n);
|
|
1067
|
+
else return "";
|
|
1068
|
+
};
|
|
1378
1069
|
|
|
1379
1070
|
/**
|
|
1380
|
-
* qualifiedIdentifier2TS
|
|
1071
|
+
* qualifiedIdentifier2TS
|
|
1381
1072
|
*/
|
|
1382
1073
|
export const qualifiedIdentifier2TS = (n: ast.QualifiedIdentifier) =>
|
|
1383
|
-
|
|
1074
|
+
`${n.qualifier}.${n.member}`;
|
|
1384
1075
|
|
|
1385
1076
|
/**
|
|
1386
|
-
* unqualifiedIdentifier2TS
|
|
1077
|
+
* unqualifiedIdentifier2TS
|
|
1387
1078
|
*/
|
|
1388
1079
|
export const unqualifiedIdentifier2TS = (n: ast.UnqualifiedIdentifier) =>
|
|
1389
|
-
|
|
1080
|
+
`${toPrim(n.value)}`;
|
|
1390
1081
|
|
|
1391
|
-
const toPrim = (id: string) => prims.indexOf(id) > -1 ? id.toLowerCase() : id;
|
|
1082
|
+
const toPrim = (id: string) => (prims.indexOf(id) > -1 ? id.toLowerCase() : id);
|