Skip to content

Commit 5b79f59

Browse files
committed
wasm: IR exhaustiveness
1 parent 73c9a0b commit 5b79f59

2 files changed

Lines changed: 30 additions & 12 deletions

File tree

packages/wasm/src/index.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -913,13 +913,8 @@ export class Compiler {
913913

914914
const insertDispatches = (exp, patterns) =>
915915
ir.rewrite(exp, {
916-
Apply: app => {
917-
if (app.children.length === 0) return app;
918-
return {type: 'Dispatch', child: app, patterns};
919-
},
920-
Param: p => {
921-
return {type: 'Dispatch', child: p, patterns};
922-
},
916+
Apply: app => (app.children.length === 0 ? app : ir.dispatch(app, patterns)),
917+
Param: p => ir.dispatch(p, patterns),
923918
});
924919

925920
// Save the observed patterns of the parameterized rules.

packages/wasm/src/ir.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,17 @@ export const caseInsensitive = (value: string): CaseInsensitive => ({
7070
});
7171

7272
export interface Dispatch {
73-
child: Apply | Param;
73+
type: 'Dispatch';
74+
child: Expr;
7475
patterns: Expr[][];
7576
}
7677

78+
export const dispatch = (child: Apply | Param, patterns: Expr[][]): Dispatch => ({
79+
type: 'Dispatch',
80+
child,
81+
patterns
82+
});
83+
7784
// TODO: Eliminate this, and replace with Not(Any())?
7885
export interface End {
7986
type: 'End';
@@ -175,6 +182,10 @@ export const liftedTerminal = (terminalId: number): LiftedTerminal => ({
175182
// Helpers
176183
// -------
177184

185+
function unreachable(x: never, msg: string): never {
186+
throw new Error(msg);
187+
}
188+
178189
function checkNotNull<T>(x: T, msg = 'unexpected null value'): NonNullable<T> {
179190
if (x == null) throw new Error(msg);
180191
return x;
@@ -192,6 +203,7 @@ export function collectParams(exp: Expr, seen = new Set<number>()) {
192203
case 'Apply':
193204
case 'Seq':
194205
return exp.children.flatMap(c => collectParams(c, seen));
206+
case 'Dispatch':
195207
case 'Lex':
196208
case 'Lookahead':
197209
case 'Not':
@@ -200,13 +212,16 @@ export function collectParams(exp: Expr, seen = new Set<number>()) {
200212
case 'Star':
201213
return collectParams(exp.child, seen);
202214
case 'Any':
215+
case 'ApplyGeneralized':
216+
case 'CaseInsensitive':
203217
case 'End':
218+
case 'LiftedTerminal':
204219
case 'Range':
205220
case 'Terminal':
206221
case 'UnicodeChar':
207222
return [];
208223
default:
209-
throw new Error(`not handled: ${exp.type}`);
224+
unreachable(exp, `not handled: ${exp}`);
210225
}
211226
}
212227

@@ -220,6 +235,8 @@ export function substituteParams(exp: Expr, actuals: Expr[]) {
220235
exp.ruleName,
221236
exp.children.map(c => substituteParams(c, actuals))
222237
);
238+
case 'Dispatch':
239+
return dispatch(substituteParams(exp.child, actuals), exp.patterns);
223240
case 'Alt':
224241
case 'Seq':
225242
return {
@@ -234,14 +251,16 @@ export function substituteParams(exp: Expr, actuals: Expr[]) {
234251
case 'Star':
235252
return {type: exp.type, child: substituteParams(exp.child, actuals)};
236253
case 'Any':
254+
case 'ApplyGeneralized':
255+
case 'CaseInsensitive':
237256
case 'End':
238257
case 'LiftedTerminal':
239258
case 'Range':
240259
case 'Terminal':
241260
case 'UnicodeChar':
242261
return exp;
243262
default:
244-
throw new Error(`not handled: ${exp.type}`);
263+
unreachable(exp, `not handled: ${exp}`);
245264
}
246265
}
247266

@@ -264,7 +283,7 @@ export type RewriteActions = {
264283
[K in ExprType]?: (exp: Extract<Expr, {type: K}>) => Expr;
265284
};
266285

267-
export function rewrite(exp: Expr, actions: RewriteActions) {
286+
export function rewrite(exp: Expr, actions: RewriteActions): Expr {
268287
const action = actions[exp.type];
269288
if (action) {
270289
return action(exp as any);
@@ -276,13 +295,17 @@ export function rewrite(exp: Expr, actions: RewriteActions) {
276295
return {type: exp.type, children: exp.children.map((e: Expr) => rewrite(e, actions))};
277296
case 'Any':
278297
case 'Apply':
298+
case 'ApplyGeneralized':
299+
case 'CaseInsensitive':
279300
case 'End':
280301
case 'LiftedTerminal':
281302
case 'Param':
282303
case 'Range':
283304
case 'Terminal':
284305
case 'UnicodeChar':
285306
return exp;
307+
case 'Dispatch':
308+
return {type: exp.type, child: rewrite(exp.child, actions), patterns: exp.patterns};
286309
case 'Lex':
287310
case 'Lookahead':
288311
case 'Not':
@@ -291,6 +314,6 @@ export function rewrite(exp: Expr, actions: RewriteActions) {
291314
case 'Star':
292315
return {type: exp.type, child: rewrite(exp.child, actions)};
293316
default:
294-
throw new Error(`not handled: ${exp.type}`);
317+
unreachable(exp, `not handled: ${exp}`);
295318
}
296319
}

0 commit comments

Comments
 (0)