main
ts 82 lines 2.08 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 import {
9 IdentifierId,
10 InstructionId,
11 Place,
12 PrunedReactiveScopeBlock,
13 ReactiveFunction,
14 isPrimitiveType,
15 isUseRefType,
16 Identifier,
17 } from '../HIR/HIR';
18 import {ReactiveFunctionVisitor, visitReactiveFunction} from './visitors';
19
20 class Visitor extends ReactiveFunctionVisitor<Set<IdentifierId>> {
21 /*
22 * Visitors don't visit lvalues as places by default, but we want to visit all places to
23 * check for reactivity
24 */
25 override visitLValue(
26 id: InstructionId,
27 lvalue: Place,
28 state: Set<IdentifierId>,
29 ): void {
30 this.visitPlace(id, lvalue, state);
31 }
32
33 /*
34 * This visitor only infers data dependencies and does not account for control dependencies
35 * where a variable may be assigned a different value based on some conditional, eg via two
36 * different paths of an if statement.
37 */
38 override visitPlace(
39 _id: InstructionId,
40 place: Place,
41 state: Set<IdentifierId>,
42 ): void {
43 if (place.reactive) {
44 state.add(place.identifier.id);
45 }
46 }
47
48 override visitPrunedScope(
49 scopeBlock: PrunedReactiveScopeBlock,
50 state: Set<IdentifierId>,
51 ): void {
52 this.traversePrunedScope(scopeBlock, state);
53
54 for (const [id, decl] of scopeBlock.scope.declarations) {
55 if (
56 !isPrimitiveType(decl.identifier) &&
57 !isStableRefType(decl.identifier, state)
58 ) {
59 state.add(id);
60 }
61 }
62 }
63 }
64 function isStableRefType(
65 identifier: Identifier,
66 reactiveIdentifiers: Set<IdentifierId>,
67 ): boolean {
68 return isUseRefType(identifier) && !reactiveIdentifiers.has(identifier.id);
69 }
70 /*
71 * Computes a set of identifiers which are reactive, using the analysis previously performed
72 * in `InferReactivePlaces`.
73 */
74 export function collectReactiveIdentifiers(
75 fn: ReactiveFunction,
76 ): Set<IdentifierId> {
77 const visitor = new Visitor();
78 const state = new Set<IdentifierId>();
79 visitReactiveFunction(fn, visitor, state);
80
81 return state;
82 }