@mirascript/typed 0.1.62 → 0.1.63
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/README.md +21 -2
- package/dist/json.d.ts +6 -1
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +174 -40
- package/dist/json.js.map +1 -1
- package/dist/parser.d.ts +41 -5
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +58 -1
- package/dist/parser.js.map +1 -1
- package/dist/type.js +1535 -471
- package/dist/type.js.map +1 -1
- package/package.json +7 -5
- package/src/json.ts +180 -45
- package/src/parser.ts +115 -10
- package/src/type.peggy +185 -45
package/src/type.peggy
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
|
+
{{
|
|
2
|
+
import { KEYWORDS } from '@mirascript/constants';
|
|
3
|
+
|
|
4
|
+
const BUILT_IN_TYPES = new Set([
|
|
5
|
+
'any',
|
|
6
|
+
'unknown',
|
|
7
|
+
'never',
|
|
8
|
+
|
|
9
|
+
'boolean',
|
|
10
|
+
'number',
|
|
11
|
+
'string',
|
|
12
|
+
'record',
|
|
13
|
+
'array',
|
|
14
|
+
'extern',
|
|
15
|
+
'module',
|
|
16
|
+
'nil',
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
const BUILT_IN_LITERALS = new Map([
|
|
20
|
+
['true', true],
|
|
21
|
+
['false', false],
|
|
22
|
+
])
|
|
23
|
+
}}
|
|
24
|
+
|
|
1
25
|
{
|
|
2
26
|
function named(name) {
|
|
27
|
+
if (KEYWORDS.includes(name)) throw new Error(`'${name}' is a reserved keyword`);
|
|
3
28
|
return name;
|
|
4
29
|
}
|
|
5
30
|
|
|
@@ -18,34 +43,35 @@ function record(fields) {
|
|
|
18
43
|
}
|
|
19
44
|
return { kind: "record", fields };
|
|
20
45
|
}
|
|
46
|
+
|
|
47
|
+
function literal(value) {
|
|
48
|
+
return { kind: "literal", value };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function string(parts) {
|
|
52
|
+
if (parts.length === 0) return '';
|
|
53
|
+
if (parts.length === 1 && parts[0].kind === 'literal') {
|
|
54
|
+
return parts[0].value;
|
|
55
|
+
}
|
|
56
|
+
return { kind: 'template', parts };
|
|
57
|
+
}
|
|
21
58
|
}
|
|
22
59
|
|
|
23
60
|
Start
|
|
24
|
-
= _
|
|
61
|
+
= _ @NamedFunction _
|
|
62
|
+
/ _ @Type _
|
|
25
63
|
|
|
26
64
|
///////////////////////////////////////////////////////////////////////////////
|
|
27
65
|
// Type (union)
|
|
28
66
|
///////////////////////////////////////////////////////////////////////////////
|
|
29
67
|
|
|
30
68
|
Type
|
|
31
|
-
=
|
|
32
|
-
return head;
|
|
33
|
-
}
|
|
69
|
+
= UnionType
|
|
34
70
|
|
|
35
71
|
UnionType
|
|
36
|
-
= _ "|" _
|
|
37
|
-
return union(
|
|
38
|
-
first,
|
|
39
|
-
...rest.map(x => x[3])
|
|
40
|
-
]);
|
|
41
|
-
}
|
|
42
|
-
/ first:PostfixType rest:(_ "|" _ PostfixType)+ {
|
|
43
|
-
return union([
|
|
44
|
-
first,
|
|
45
|
-
...rest.map(x => x[3])
|
|
46
|
-
]);
|
|
72
|
+
= _ ( "|" _ )? u:PostfixType|1.., _ "|" _ | {
|
|
73
|
+
return union(u);
|
|
47
74
|
}
|
|
48
|
-
/ PostfixType
|
|
49
75
|
|
|
50
76
|
///////////////////////////////////////////////////////////////////////////////
|
|
51
77
|
// Array
|
|
@@ -64,65 +90,179 @@ PostfixType
|
|
|
64
90
|
///////////////////////////////////////////////////////////////////////////////
|
|
65
91
|
|
|
66
92
|
PrimaryType
|
|
67
|
-
=
|
|
93
|
+
= FunctionType
|
|
94
|
+
/ name:Identifier generic:(_ "<" _ @TypeArgList _ ">")? {
|
|
68
95
|
if (generic) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
96
|
+
if (name === 'array') {
|
|
97
|
+
if (generic.length !== 1) throw new Error("'array' expects one generic type parameter");
|
|
98
|
+
return array(generic[0]);
|
|
99
|
+
}
|
|
100
|
+
if (name === 'record') {
|
|
101
|
+
if (generic.length === 1) return { kind: "record", value: generic[0] };
|
|
102
|
+
if (generic.length === 2) return { kind: "record", key: generic[0], value: generic[1] };
|
|
103
|
+
throw new Error("'record' expects one or two generic type parameters");
|
|
104
|
+
}
|
|
105
|
+
throw new Error(`'${name}' is not a generic type`);
|
|
106
|
+
}
|
|
107
|
+
if (BUILT_IN_LITERALS.has(name)) {
|
|
108
|
+
return { kind: "literal", value: BUILT_IN_LITERALS.get(name) };
|
|
109
|
+
}
|
|
110
|
+
if (BUILT_IN_TYPES.has(name)) {
|
|
111
|
+
return name;
|
|
72
112
|
}
|
|
73
|
-
if (name === 'true') return { kind: "literal", value: true };
|
|
74
|
-
if (name === 'false') return { kind: "literal", value: false };
|
|
75
113
|
return named(name);
|
|
76
114
|
}
|
|
77
115
|
/ lit:String {
|
|
78
|
-
return { kind: "literal", value: lit };
|
|
79
|
-
|
|
80
|
-
/ "(" _ t:Type _ ")" {
|
|
81
|
-
return t;
|
|
116
|
+
if (typeof lit == 'string') return { kind: "literal", value: lit };
|
|
117
|
+
return lit;
|
|
82
118
|
}
|
|
119
|
+
/ "(" _ @Type _ ")"
|
|
83
120
|
/ RecordType
|
|
84
121
|
|
|
122
|
+
|
|
123
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
124
|
+
// Generics
|
|
125
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
126
|
+
|
|
127
|
+
TypeParamList
|
|
128
|
+
= @Identifier|1.., _ "," _ | ( _ "," _ )?
|
|
129
|
+
|
|
130
|
+
TypeArgList
|
|
131
|
+
= @Type|1.., _ "," _ | ( _ "," _ )?
|
|
132
|
+
|
|
133
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
134
|
+
// Function
|
|
135
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
136
|
+
|
|
137
|
+
FunctionType
|
|
138
|
+
= "fn" _ body:FunctionBody { return body; }
|
|
139
|
+
|
|
140
|
+
NamedFunction
|
|
141
|
+
= "fn" _ name:Identifier _ body:FunctionBody {
|
|
142
|
+
if (KEYWORDS.includes(name)) throw new Error(`'${name}' is a reserved keyword`);
|
|
143
|
+
body.name = name;
|
|
144
|
+
return body;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
FunctionBody
|
|
148
|
+
= typeParams:(_ "<" _ @TypeParamList _ ">")? _ "(" _ params:FunctionParamList? _ ")" ret:(_ "->" _ @Type)? {
|
|
149
|
+
const result = { kind: "function", params: params ?? [] };
|
|
150
|
+
if (typeParams !== null) result.typeParams = typeParams.map(name => Symbol(name));
|
|
151
|
+
if (ret !== null) result.returns = ret;
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
FunctionParamList
|
|
156
|
+
= params:FunctionParam|1.., _ "," _ | ( _ "," _ )? {
|
|
157
|
+
for (let i = 0; i < params.length - 1; i++) {
|
|
158
|
+
if (params[i].spread) throw new Error("Rest parameter must be last");
|
|
159
|
+
}
|
|
160
|
+
return params;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
FunctionParam
|
|
164
|
+
= spread:".." name:Identifier? _ t:(":" _ @Type)? {
|
|
165
|
+
return {
|
|
166
|
+
name: name ?? "",
|
|
167
|
+
spread: true,
|
|
168
|
+
type: t ?? { kind: "array", element: "any" }
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/ name:Identifier _ t:(":" _ @Type)? {
|
|
172
|
+
return { name, type: t ?? "any" };
|
|
173
|
+
}
|
|
174
|
+
|
|
85
175
|
///////////////////////////////////////////////////////////////////////////////
|
|
86
176
|
// Record
|
|
87
177
|
///////////////////////////////////////////////////////////////////////////////
|
|
88
178
|
|
|
89
179
|
RecordType
|
|
90
|
-
= "(" _ ")" { return record([]); }
|
|
91
|
-
/ "(" _ fields:FieldList _ ")" { return record(fields); }
|
|
180
|
+
= "(" _ fields:FieldList? _ ")" { return record(fields ?? []); }
|
|
92
181
|
|
|
93
182
|
FieldList
|
|
94
|
-
=
|
|
95
|
-
return fields;
|
|
96
|
-
}
|
|
183
|
+
= @Field|1.., _ "," _ | ( _ "," _ )?
|
|
97
184
|
|
|
98
185
|
Field
|
|
99
186
|
= name:FieldName opt:("?"?) _ ":" _ t:Type {
|
|
100
187
|
return {
|
|
101
188
|
name,
|
|
102
|
-
optional: opt
|
|
103
|
-
type: t
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
/ t:Type {
|
|
107
|
-
return {
|
|
189
|
+
optional: opt != null,
|
|
108
190
|
type: t
|
|
109
191
|
};
|
|
110
192
|
}
|
|
193
|
+
/ type:Type { return { type }; }
|
|
111
194
|
|
|
112
195
|
FieldName
|
|
113
196
|
= Identifier
|
|
114
|
-
/ String
|
|
197
|
+
/ name:String {
|
|
198
|
+
if (typeof name != 'string') throw new Error('Field name must be a string literal');
|
|
199
|
+
return name;
|
|
200
|
+
}
|
|
115
201
|
|
|
116
202
|
///////////////////////////////////////////////////////////////////////////////
|
|
117
203
|
// Lexer
|
|
118
204
|
///////////////////////////////////////////////////////////////////////////////
|
|
119
205
|
|
|
120
|
-
|
|
121
|
-
=
|
|
122
|
-
|
|
206
|
+
HexDigit "hex digit"
|
|
207
|
+
= [0-9a-f]i
|
|
208
|
+
|
|
209
|
+
EscapeSequence
|
|
210
|
+
= "\\" char:(['"`\\nrtbfv0$]) {
|
|
211
|
+
switch (char) {
|
|
212
|
+
case 'n': return '\n';
|
|
213
|
+
case 'r': return '\r';
|
|
214
|
+
case 't': return '\t';
|
|
215
|
+
case 'b': return '\b';
|
|
216
|
+
case 'f': return '\f';
|
|
217
|
+
case 'v': return '\v';
|
|
218
|
+
case '0': return '\0';
|
|
219
|
+
default: return char;
|
|
220
|
+
}
|
|
221
|
+
} / "\\x" hex:$(HexDigit HexDigit) {
|
|
222
|
+
const code = parseInt(hex, 16);
|
|
223
|
+
// Valid ASCII characters are in the range 0x00 to 0x7F.
|
|
224
|
+
if (code >= 128) throw new Error(`Invalid hex escape sequence: \\x${hex}`);
|
|
225
|
+
return String.fromCharCode(code);
|
|
226
|
+
} / "\\u{" hex:$(HexDigit+) "}" {
|
|
227
|
+
const code = parseInt(hex, 16);
|
|
228
|
+
// Valid Unicode code points are in the range 0x0000 to 0x10FFFF, not including the surrogate halves (0xD800 to 0xDFFF).
|
|
229
|
+
if (code > 0x10FFFF || (code >= 0xD800 && code <= 0xDFFF)) {
|
|
230
|
+
throw new Error(`Invalid Unicode code point: \\u{${hex}}`);
|
|
231
|
+
}
|
|
232
|
+
return String.fromCodePoint(code);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
String "string"
|
|
236
|
+
= '"' parts:DoubleQuotePart* '"' { return string(parts); }
|
|
237
|
+
/ "'" parts:SingleQuotePart* "'" { return string(parts); }
|
|
238
|
+
/ "`" parts:BacktickPart* "`" { return string(parts); }
|
|
239
|
+
|
|
240
|
+
DoubleQuotePart
|
|
241
|
+
= "$" "(" _ @Type _ ")"
|
|
242
|
+
/ chars:DoubleQuoteChar+ { return literal(chars.join('')); }
|
|
243
|
+
|
|
244
|
+
SingleQuotePart
|
|
245
|
+
= "$" "(" _ @Type _ ")"
|
|
246
|
+
/ chars:SingleQuoteChar+ { return literal(chars.join('')); }
|
|
247
|
+
|
|
248
|
+
BacktickPart
|
|
249
|
+
= "$" "(" _ @Type _ ")"
|
|
250
|
+
/ chars:BacktickChar+ { return literal(chars.join('')); }
|
|
251
|
+
|
|
252
|
+
DoubleQuoteChar
|
|
253
|
+
= EscapeSequence
|
|
254
|
+
/ $[^\\$"]+
|
|
255
|
+
|
|
256
|
+
SingleQuoteChar
|
|
257
|
+
= EscapeSequence
|
|
258
|
+
/ $[^\\$']+
|
|
259
|
+
|
|
260
|
+
BacktickChar
|
|
261
|
+
= EscapeSequence
|
|
262
|
+
/ $[^\\$`]+
|
|
123
263
|
|
|
124
|
-
Identifier
|
|
125
|
-
= $([
|
|
264
|
+
Identifier "identifier"
|
|
265
|
+
= $(("_"+ / "@"+ / "$"+ / [\p{XID_Start}]u) [\p{XID_Continue}]u*)
|
|
126
266
|
|
|
127
|
-
_
|
|
128
|
-
= [ \t\r\n]*
|
|
267
|
+
_ "whitespace"
|
|
268
|
+
= [ \t\v\f\r\n]*
|