main
rs 248 lines 6.98 KB
Raw
1 // Copyright (c) Meta Platforms, Inc. and affiliates.
2 //
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the root directory of this source tree.
5
6 //! Reactive function types — tree representation of a compiled function.
7 //!
8 //! `ReactiveFunction` is derived from the HIR CFG by `BuildReactiveFunction`.
9 //! Control flow constructs (if/switch/loops/try) and reactive scopes become
10 //! nested blocks rather than block references.
11 //!
12 //! Corresponds to the reactive types in `HIR.ts`.
13
14 use react_compiler_diagnostics::SourceLocation;
15
16 use crate::{
17 AliasingEffect, BlockId, EvaluationOrder, InstructionValue, LogicalOperator, ParamPattern,
18 Place, ScopeId,
19 };
20
21 // =============================================================================
22 // ReactiveFunction
23 // =============================================================================
24
25 /// Tree representation of a compiled function, converted from the CFG-based HIR.
26 /// TS: ReactiveFunction in HIR.ts
27 #[derive(Debug, Clone)]
28 pub struct ReactiveFunction {
29 pub loc: Option<SourceLocation>,
30 pub id: Option<String>,
31 pub name_hint: Option<String>,
32 pub params: Vec<ParamPattern>,
33 pub generator: bool,
34 pub is_async: bool,
35 pub body: ReactiveBlock,
36 pub directives: Vec<String>,
37 // No env field — passed separately per established Rust convention
38 }
39
40 // =============================================================================
41 // ReactiveBlock and ReactiveStatement
42 // =============================================================================
43
44 /// TS: ReactiveBlock = Array<ReactiveStatement>
45 pub type ReactiveBlock = Vec<ReactiveStatement>;
46
47 /// TS: ReactiveStatement (discriminated union with 'kind' field)
48 #[derive(Debug, Clone)]
49 pub enum ReactiveStatement {
50 Instruction(ReactiveInstruction),
51 Terminal(ReactiveTerminalStatement),
52 Scope(ReactiveScopeBlock),
53 PrunedScope(PrunedReactiveScopeBlock),
54 }
55
56 // =============================================================================
57 // ReactiveInstruction and ReactiveValue
58 // =============================================================================
59
60 /// TS: ReactiveInstruction
61 #[derive(Debug, Clone)]
62 pub struct ReactiveInstruction {
63 pub id: EvaluationOrder,
64 pub lvalue: Option<Place>,
65 pub value: ReactiveValue,
66 pub effects: Option<Vec<AliasingEffect>>,
67 pub loc: Option<SourceLocation>,
68 }
69
70 /// Extends InstructionValue with compound expression types that were
71 /// separate blocks+terminals in HIR but become nested expressions here.
72 /// TS: ReactiveValue = InstructionValue | ReactiveLogicalValue | ...
73 #[derive(Debug, Clone)]
74 pub enum ReactiveValue {
75 /// All ~35 base instruction value kinds
76 Instruction(InstructionValue),
77
78 /// TS: ReactiveLogicalValue
79 LogicalExpression {
80 operator: LogicalOperator,
81 left: Box<ReactiveValue>,
82 right: Box<ReactiveValue>,
83 loc: Option<SourceLocation>,
84 },
85
86 /// TS: ReactiveTernaryValue
87 ConditionalExpression {
88 test: Box<ReactiveValue>,
89 consequent: Box<ReactiveValue>,
90 alternate: Box<ReactiveValue>,
91 loc: Option<SourceLocation>,
92 },
93
94 /// TS: ReactiveSequenceValue
95 SequenceExpression {
96 instructions: Vec<ReactiveInstruction>,
97 id: EvaluationOrder,
98 value: Box<ReactiveValue>,
99 loc: Option<SourceLocation>,
100 },
101
102 /// TS: ReactiveOptionalCallValue
103 OptionalExpression {
104 id: EvaluationOrder,
105 value: Box<ReactiveValue>,
106 optional: bool,
107 loc: Option<SourceLocation>,
108 },
109 }
110
111 // =============================================================================
112 // Terminals
113 // =============================================================================
114
115 #[derive(Debug, Clone)]
116 pub struct ReactiveTerminalStatement {
117 pub terminal: ReactiveTerminal,
118 pub label: Option<ReactiveLabel>,
119 }
120
121 #[derive(Debug, Clone)]
122 pub struct ReactiveLabel {
123 pub id: BlockId,
124 pub implicit: bool,
125 }
126
127 #[derive(Debug, Clone, PartialEq, Eq)]
128 pub enum ReactiveTerminalTargetKind {
129 Implicit,
130 Labeled,
131 Unlabeled,
132 }
133
134 impl std::fmt::Display for ReactiveTerminalTargetKind {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 match self {
137 ReactiveTerminalTargetKind::Implicit => write!(f, "implicit"),
138 ReactiveTerminalTargetKind::Labeled => write!(f, "labeled"),
139 ReactiveTerminalTargetKind::Unlabeled => write!(f, "unlabeled"),
140 }
141 }
142 }
143
144 #[derive(Debug, Clone)]
145 pub enum ReactiveTerminal {
146 Break {
147 target: BlockId,
148 id: EvaluationOrder,
149 target_kind: ReactiveTerminalTargetKind,
150 loc: Option<SourceLocation>,
151 },
152 Continue {
153 target: BlockId,
154 id: EvaluationOrder,
155 target_kind: ReactiveTerminalTargetKind,
156 loc: Option<SourceLocation>,
157 },
158 Return {
159 value: Place,
160 id: EvaluationOrder,
161 loc: Option<SourceLocation>,
162 },
163 Throw {
164 value: Place,
165 id: EvaluationOrder,
166 loc: Option<SourceLocation>,
167 },
168 Switch {
169 test: Place,
170 cases: Vec<ReactiveSwitchCase>,
171 id: EvaluationOrder,
172 loc: Option<SourceLocation>,
173 },
174 DoWhile {
175 loop_block: ReactiveBlock,
176 test: ReactiveValue,
177 id: EvaluationOrder,
178 loc: Option<SourceLocation>,
179 },
180 While {
181 test: ReactiveValue,
182 loop_block: ReactiveBlock,
183 id: EvaluationOrder,
184 loc: Option<SourceLocation>,
185 },
186 For {
187 init: ReactiveValue,
188 test: ReactiveValue,
189 update: Option<ReactiveValue>,
190 loop_block: ReactiveBlock,
191 id: EvaluationOrder,
192 loc: Option<SourceLocation>,
193 },
194 ForOf {
195 init: ReactiveValue,
196 test: ReactiveValue,
197 loop_block: ReactiveBlock,
198 id: EvaluationOrder,
199 loc: Option<SourceLocation>,
200 },
201 ForIn {
202 init: ReactiveValue,
203 loop_block: ReactiveBlock,
204 id: EvaluationOrder,
205 loc: Option<SourceLocation>,
206 },
207 If {
208 test: Place,
209 consequent: ReactiveBlock,
210 alternate: Option<ReactiveBlock>,
211 id: EvaluationOrder,
212 loc: Option<SourceLocation>,
213 },
214 Label {
215 block: ReactiveBlock,
216 id: EvaluationOrder,
217 loc: Option<SourceLocation>,
218 },
219 Try {
220 block: ReactiveBlock,
221 handler_binding: Option<Place>,
222 handler: ReactiveBlock,
223 id: EvaluationOrder,
224 loc: Option<SourceLocation>,
225 },
226 }
227
228 #[derive(Debug, Clone)]
229 pub struct ReactiveSwitchCase {
230 pub test: Option<Place>,
231 pub block: Option<ReactiveBlock>,
232 }
233
234 // =============================================================================
235 // Scope Blocks
236 // =============================================================================
237
238 #[derive(Debug, Clone)]
239 pub struct ReactiveScopeBlock {
240 pub scope: ScopeId,
241 pub instructions: ReactiveBlock,
242 }
243
244 #[derive(Debug, Clone)]
245 pub struct PrunedReactiveScopeBlock {
246 pub scope: ScopeId,
247 pub instructions: ReactiveBlock,
248 }