import {
IdentifierId,
InstructionId,
Place,
PrunedReactiveScopeBlock,
ReactiveFunction,
isPrimitiveType,
isUseRefType,
Identifier,
} from '../HIR/HIR';
import {ReactiveFunctionVisitor, visitReactiveFunction} from './visitors';
class Visitor extends ReactiveFunctionVisitor<Set<IdentifierId>> {
override visitLValue(
id: InstructionId,
lvalue: Place,
state: Set<IdentifierId>,
): void {
this.visitPlace(id, lvalue, state);
}
override visitPlace(
_id: InstructionId,
place: Place,
state: Set<IdentifierId>,
): void {
if (place.reactive) {
state.add(place.identifier.id);
}
}
override visitPrunedScope(
scopeBlock: PrunedReactiveScopeBlock,
state: Set<IdentifierId>,
): void {
this.traversePrunedScope(scopeBlock, state);
for (const [id, decl] of scopeBlock.scope.declarations) {
if (
!isPrimitiveType(decl.identifier) &&
!isStableRefType(decl.identifier, state)
) {
state.add(id);
}
}
}
}
function isStableRefType(
identifier: Identifier,
reactiveIdentifiers: Set<IdentifierId>,
): boolean {
return isUseRefType(identifier) && !reactiveIdentifiers.has(identifier.id);
}
export function collectReactiveIdentifiers(
fn: ReactiveFunction,
): Set<IdentifierId> {
const visitor = new Visitor();
const state = new Set<IdentifierId>();
visitReactiveFunction(fn, visitor, state);
return state;
}