import {
ReactiveFunction,
ReactiveScopeBlock,
ReactiveStatement,
ReactiveTerminal,
ReactiveTerminalStatement,
} from '../HIR/HIR';
import {assertExhaustive} from '../Utils/utils';
import {
ReactiveFunctionTransform,
Transformed,
visitReactiveFunction,
} from './visitors';
export function flattenReactiveLoops(fn: ReactiveFunction): void {
visitReactiveFunction(fn, new Transform(), false);
}
class Transform extends ReactiveFunctionTransform<boolean> {
override transformScope(
scope: ReactiveScopeBlock,
isWithinLoop: boolean,
): Transformed<ReactiveStatement> {
this.visitScope(scope, isWithinLoop);
if (isWithinLoop) {
return {
kind: 'replace',
value: {
kind: 'pruned-scope',
scope: scope.scope,
instructions: scope.instructions,
},
};
} else {
return {kind: 'keep'};
}
}
override visitTerminal(
stmt: ReactiveTerminalStatement<ReactiveTerminal>,
isWithinLoop: boolean,
): void {
switch (stmt.terminal.kind) {
case 'do-while':
case 'while':
case 'for':
case 'for-of':
case 'for-in': {
this.traverseTerminal(stmt, true);
break;
}
case 'try':
case 'label':
case 'break':
case 'continue':
case 'if':
case 'return':
case 'switch':
case 'throw': {
this.traverseTerminal(stmt, isWithinLoop);
break;
}
default: {
assertExhaustive(
stmt.terminal,
`Unexpected terminal kind \`${(stmt.terminal as any).kind}\``,
);
}
}
}
}