import {
ReactiveFunction,
ReactiveScopeBlock,
ReactiveStatement,
ReactiveTerminalStatement,
} from '../HIR/HIR';
import {
ReactiveFunctionTransform,
Transformed,
visitReactiveFunction,
} from './visitors';
export function pruneUnusedScopes(fn: ReactiveFunction): void {
visitReactiveFunction(fn, new Transform(), {
hasReturnStatement: false,
} as State);
}
type State = {
hasReturnStatement: boolean;
};
class Transform extends ReactiveFunctionTransform<State> {
override visitTerminal(stmt: ReactiveTerminalStatement, state: State): void {
this.traverseTerminal(stmt, state);
if (stmt.terminal.kind === 'return') {
state.hasReturnStatement = true;
}
}
override transformScope(
scopeBlock: ReactiveScopeBlock,
_state: State,
): Transformed<ReactiveStatement> {
const scopeState: State = {hasReturnStatement: false};
this.visitScope(scopeBlock, scopeState);
if (
!scopeState.hasReturnStatement &&
scopeBlock.scope.reassignments.size === 0 &&
(scopeBlock.scope.declarations.size === 0 ||
!hasOwnDeclaration(scopeBlock))
) {
return {
kind: 'replace',
value: {
kind: 'pruned-scope',
scope: scopeBlock.scope,
instructions: scopeBlock.instructions,
},
};
} else {
return {kind: 'keep'};
}
}
}
function hasOwnDeclaration(block: ReactiveScopeBlock): boolean {
for (const declaration of block.scope.declarations.values()) {
if (declaration.scope.id === block.scope.id) {
return true;
}
}
return false;
}